Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds more tests to ynLSD #35

Merged
merged 8 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions test/foundry/integration/LSDStakingNode.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ contract LSDStakingNodeTest is IntegrationBaseTest {
(bool success, ) = chainAddresses.lsd.STETH_ADDRESS.call{value: amount + 1}("");
require(success, "ETH transfer failed");
uint256 balance = stETH.balanceOf(address(this));
assertEq(balance, amount, "Amount not received");
assertEq(compareWithThreshold(balance, amount, 1), true, "Amount not received");
stETH.approve(address(ynlsd), amount);
ynlsd.deposit(stETH, amount, address(this));

Expand Down Expand Up @@ -85,7 +85,7 @@ contract LSDStakingNodeTest is IntegrationBaseTest {
(bool success, ) = chainAddresses.lsd.STETH_ADDRESS.call{value: amount + 1}("");
require(success, "ETH transfer failed");
uint256 balance = stETH.balanceOf(address(this));
assertEq(balance, amount, "Amount not received");
assertEq(compareWithThreshold(balance, amount, 1), true, "Amount not received");
stETH.approve(address(ynlsd), amount);
ynlsd.deposit(stETH, amount, address(this));

Expand All @@ -98,7 +98,6 @@ contract LSDStakingNodeTest is IntegrationBaseTest {
vm.expectRevert("Pausable: index is paused");
lsdStakingNode.depositAssetsToEigenlayer(assets, amounts);
}

}


Expand Down
139 changes: 130 additions & 9 deletions test/foundry/integration/StakingNodesManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ pragma solidity ^0.8.24;
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {IntegrationBaseTest} from "./IntegrationBaseTest.sol";
import {IStakingNode} from "../../../src/interfaces/IStakingNode.sol";
import {IEigenPod} from "../../../src/external/eigenlayer/v0.1.0/interfaces/IEigenPod.sol";
import {IStakingNodesManager} from "../../../src/interfaces/IStakingNodesManager.sol";
import {StakingNodesManager} from "../../../src/StakingNodesManager.sol";
import {ynETH} from "../../../src/ynETH.sol";
import {TestStakingNodeV2} from "../mocks/TestStakingNodeV2.sol";
import {TestStakingNodesManagerV2} from "../mocks/TestStakingNodesManagerV2.sol";
import {IntegrationBaseTest} from "test/foundry/integration/IntegrationBaseTest.sol";
import {IStakingNode} from "src/interfaces/IStakingNode.sol";
import {IEigenPod} from "src/external/eigenlayer/v0.1.0/interfaces/IEigenPod.sol";
import {IStakingNodesManager} from "src/interfaces/IStakingNodesManager.sol";
import {StakingNodesManager} from "src/StakingNodesManager.sol";
import {ynETH} from "src/ynETH.sol";
import {TestStakingNodeV2} from "test/foundry/mocks/TestStakingNodeV2.sol";
import {TestStakingNodesManagerV2} from "test/foundry/mocks/TestStakingNodesManagerV2.sol";


contract StakingNodesManagerStakingNodeCreation is IntegrationBaseTest {
Expand Down Expand Up @@ -98,6 +98,20 @@ contract StakingNodesManagerStakingNodeCreation is IntegrationBaseTest {
uint256 updatedMaxNodeCount = stakingNodesManager.maxNodeCount();
assertEq(updatedMaxNodeCount, newMaxNodeCount, "Max node count does not match expected value");
}

function testTooManyStakingNodes() public {
// set the max node count to 1
vm.prank(actors.STAKING_ADMIN);
stakingNodesManager.setMaxNodeCount(1);
uint256 maxNodeCount = stakingNodesManager.maxNodeCount();
// create first statking node
vm.prank(actors.STAKING_NODE_CREATOR);
stakingNodesManager.createStakingNode();
// create second staking node should fail
vm.prank(actors.STAKING_NODE_CREATOR);
vm.expectRevert(abi.encodeWithSelector(StakingNodesManager.TooManyStakingNodes.selector, maxNodeCount));
stakingNodesManager.createStakingNode();
}
}

contract StakingNodesManagerStakingNodeImplementation is IntegrationBaseTest {
Expand Down Expand Up @@ -149,14 +163,14 @@ contract StakingNodesManagerStakingNodeImplementation is IntegrationBaseTest {
assertEq(stakingNodesManager.isStakingNodesAdmin(actors.STAKING_NODES_ADMIN), true);
}

// TODO: Should createStakingNode be open to public?
function testStakingNodesLength() public {
uint256 initialLength = stakingNodesManager.nodesLength();
vm.prank(actors.STAKING_NODE_CREATOR);
stakingNodesManager.createStakingNode();
uint256 newLength = stakingNodesManager.nodesLength();
assertEq(newLength, initialLength + 1);
}

}

contract StakingNodesManagerRegisterValidators is IntegrationBaseTest {
Expand Down Expand Up @@ -427,6 +441,113 @@ contract StakingNodesManagerViews is IntegrationBaseTest {
}
}

contract StakingNodesManagerValidators is IntegrationBaseTest {

function makeTestValidators(uint256 _depositAmount) public returns(IStakingNodesManager.ValidatorData[] memory validatorData, uint256 validatorCount) {
address addr1 = vm.addr(100);
vm.deal(addr1, 100 ether);
validatorCount = 3;
uint256 depositAmount = _depositAmount * validatorCount;
vm.prank(addr1);
yneth.depositETH{value: depositAmount}(addr1);

vm.prank(actors.STAKING_NODE_CREATOR);
stakingNodesManager.createStakingNode();

vm.prank(actors.STAKING_NODE_CREATOR);
stakingNodesManager.createStakingNode();

vm.prank(actors.STAKING_NODE_CREATOR);
stakingNodesManager.createStakingNode();

validatorData = new IStakingNodesManager.ValidatorData[](validatorCount);

validatorData[0] = IStakingNodesManager.ValidatorData({
publicKey: ZERO_PUBLIC_KEY,
signature: ZERO_SIGNATURE,
nodeId: 0,
depositDataRoot: bytes32(0)
});
validatorData[1] = IStakingNodesManager.ValidatorData({
publicKey: ONE_PUBLIC_KEY,
signature: ZERO_SIGNATURE,
nodeId: 1,
depositDataRoot: bytes32(0)
});

validatorData[2] = IStakingNodesManager.ValidatorData({
publicKey: TWO_PUBLIC_KEY,
signature: ZERO_SIGNATURE,
nodeId: 2,
depositDataRoot: bytes32(0)
});

for (uint256 i = 0; i < validatorData.length; i++) {
bytes memory withdrawalCredentials = stakingNodesManager.getWithdrawalCredentials(validatorData[i].nodeId);
uint256 amount = depositAmount / validatorData.length;
bytes32 depositDataRoot = stakingNodesManager.generateDepositRoot(
validatorData[i].publicKey,
validatorData[i].signature,
withdrawalCredentials, amount
);
validatorData[i].depositDataRoot = depositDataRoot;
}
}

function testRegisterValidatorDepositDataRootMismatch() public {
uint256 depositAmount = 33 ether;
(IStakingNodesManager.ValidatorData[] memory validatorData,) = makeTestValidators(depositAmount);
// try to create a bad deposit root
bytes32 depositRoot = depositContractEth2.get_deposit_root();

vm.prank(actors.VALIDATOR_MANAGER);
vm.expectRevert(abi.encodeWithSelector(
StakingNodesManager.DepositDataRootMismatch.selector,
0x7be1a5aee0180c84f2d1b0ef721fb62bf323ee9aabeac0bd5bb551da1782f805,
validatorData[0].depositDataRoot)
);
stakingNodesManager.registerValidators(depositRoot, validatorData);
}

function testRegisterValidatorSuccess() public {
(IStakingNodesManager.ValidatorData[] memory validatorData, uint256 validatorCount) = makeTestValidators(32 ether);
// Call validateDepositDataAllocation to ensure the deposit data allocation ßis valid
stakingNodesManager.validateDepositDataAllocation(validatorData);

bytes32 depositRoot = depositContractEth2.get_deposit_root();
vm.prank(actors.VALIDATOR_MANAGER);
stakingNodesManager.registerValidators(depositRoot, validatorData);

StakingNodesManager.Validator[] memory registeredValidators = stakingNodesManager.getAllValidators();
assertEq(registeredValidators.length, validatorCount, "Incorrect number of registered validators");
}

function testGenerateWithdrawalCredentials() public {
makeTestValidators(32 ether);

bytes memory withdrawalCredentials = stakingNodesManager.generateWithdrawalCredentials(actors.VALIDATOR_MANAGER);
assertEq(withdrawalCredentials.length, 32, "Withdrawal credentials length does not match expected value");
}

}

contract StakingNodeManagerWithdrawals is IntegrationBaseTest {

function testProcessWithdrawnETH() public {
address addr1 = vm.addr(100);
vm.deal(addr1, 100 ether);
uint256 depositAmount = 32 ether;
vm.prank(addr1);
yneth.depositETH{value: depositAmount}(addr1);
vm.prank(actors.STAKING_NODE_CREATOR);
stakingNodesManager.createStakingNode();
uint256 amountToWithdraw = 10 ether;
vm.expectRevert(abi.encodeWithSelector(StakingNodesManager.NotStakingNode.selector, actors.STAKING_NODE_CREATOR, 0));
vm.prank(actors.STAKING_NODE_CREATOR);
stakingNodesManager.processWithdrawnETH(0, amountToWithdraw);
}
}

contract StakingNodesManagerMisc is IntegrationBaseTest {

function testSendingETHToStakingNodesManagerShouldRevert() public {
Expand Down
53 changes: 37 additions & 16 deletions test/foundry/integration/ynLSD.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.s
import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {AggregatorV3Interface} from "../../../src/external/chainlink/AggregatorV3Interface.sol";
import {IPausable} from "../../../src/external/eigenlayer/v0.1.0/interfaces//IPausable.sol";
import {ILSDStakingNode} from "../../../src/interfaces/ILSDStakingNode.sol";
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";

import {AggregatorV3Interface} from "src/external/chainlink/AggregatorV3Interface.sol";
import {IPausable} from "src/external/eigenlayer/v0.1.0/interfaces//IPausable.sol";
import {ILSDStakingNode} from "src/interfaces/ILSDStakingNode.sol";
import {TestLSDStakingNodeV2} from "test/foundry/mocks/TestLSDStakingNodeV2.sol";
import {TestYnLSDV2} from "test/foundry/mocks/TestYnLSDV2.sol";
import {ynBase} from "src/ynBase.sol";


contract ynLSDAssetTest is IntegrationBaseTest {
Expand All @@ -27,14 +24,12 @@ contract ynLSDAssetTest is IntegrationBaseTest {
vm.prank(actors.STAKING_NODE_CREATOR);
ILSDStakingNode lsdStakingNode = ynlsd.createLSDStakingNode();

// Obtain STETH
// Obtain STETH

(bool success, ) = chainAddresses.lsd.STETH_ADDRESS.call{value: amount + 1}("");
require(success, "ETH transfer failed");
//asset.transfer(destination, amount + 1);
assertEq(compareWithThreshold(asset.balanceOf(address(this)), amount, 1), true, "Amount not received");
vm.stopPrank();
uint256 balance = asset.balanceOf(address(this));
emit log_uint(balance);
assertEq(balance, amount, "Amount not received");

asset.approve(address(ynlsd), amount);

Expand Down Expand Up @@ -174,8 +169,7 @@ contract ynLSDAssetTest is IntegrationBaseTest {
(bool success, ) = chainAddresses.lsd.STETH_ADDRESS.call{value: amount + 1}("");
require(success, "ETH transfer failed");
uint256 balance = asset.balanceOf(address(this));
emit log_uint(balance);
assertEq(balance, amount, "Amount not received");
assertEq(compareWithThreshold(balance, amount, 1), true, "Amount not received");
asset.approve(address(ynlsd), amount);
ynlsd.deposit(asset, amount, address(this));

Expand All @@ -202,6 +196,33 @@ contract ynLSDAssetTest is IntegrationBaseTest {
// Assert that totalAssets reflects the deposit
assertEq(totalAssetsAfterDeposit, expectedBalance, "Total assets do not reflect the deposit");
}

function testPreviewDeposit() public {
IERC20 asset = IERC20(chainAddresses.lsd.STETH_ADDRESS);
uint256 amount = 1 ether;

AggregatorV3Interface priceFeed = AggregatorV3Interface(chainAddresses.lsd.STETH_FEED_ADDRESS);
(, int256 price,,,) = priceFeed.latestRoundData();
uint256 stethPrice = uint256(price);

uint256 expectedDepositPreview = amount * stethPrice / 1e18;
uint256 previewDeposit = ynlsd.previewDeposit(asset, amount);
assertEq(previewDeposit, expectedDepositPreview, "Preview deposit does not match expected value");
}

function testConvertToETH() public {
IERC20 asset = IERC20(chainAddresses.lsd.STETH_ADDRESS);
uint256 amount = 1 ether;

AggregatorV3Interface priceFeed = AggregatorV3Interface(chainAddresses.lsd.STETH_FEED_ADDRESS);
(, int256 price,,,) = priceFeed.latestRoundData();
uint256 stethPrice = uint256(price);

uint256 expectedDepositPreview = amount * stethPrice / 1e18;

uint256 ethAmount = ynlsd.convertToETH(asset, amount);
assertEq(ethAmount, expectedDepositPreview, "convertToEth does not match expected value");
}
}

contract ynLSDAdminTest is IntegrationBaseTest {
Expand Down