Skip to content

Commit

Permalink
add stake32EthValidated
Browse files Browse the repository at this point in the history
  • Loading branch information
manoj9april committed Feb 13, 2024
1 parent 026d228 commit 630dc38
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 3 deletions.
38 changes: 35 additions & 3 deletions contracts/NodeDelegator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/securit
import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";

import { IEigenPodManager } from "./interfaces/IEigenPodManager.sol";
import { IEigenPod, BeaconChainProofs } from "./interfaces/IEigenPod.sol";
import { IEigenPod, BeaconChainProofs, IBeaconDeposit } from "./interfaces/IEigenPod.sol";

/// @title NodeDelegator Contract
/// @notice The contract that handles the depositing of assets into strategies
Expand Down Expand Up @@ -181,11 +181,43 @@ contract NodeDelegator is INodeDelegator, LRTConfigRoleChecker, PausableUpgradea
whenNotPaused
onlyLRTOperator
{
// Call the stake function in the EigenPodManager
IEigenPodManager eigenPodManager = IEigenPodManager(lrtConfig.getContract(LRTConstants.EIGEN_POD_MANAGER));
eigenPodManager.stake{ value: 32 ether }(pubkey, signature, depositDataRoot);

// Increment the staked but not verified ETH
// tracks staked but unverified native ETH
stakedButUnverifiedNativeETH += 32 ether;

emit ETHStaked(pubkey, 32 ether);
}

/// @notice Stake ETH from NDC into EigenLayer
/// @param pubkey The pubkey of the validator
/// @param signature The signature of the validator
/// @param depositDataRoot The deposit data root of the validator
/// @param expectedDepositRoot The expected deposit data root, which is computed offchain
/// @dev Only LRT Operator should call this function
/// @dev Exactly 32 ether is allowed, hence it is hardcoded
/// @dev offchain checks withdraw credentials authenticity
/// @dev compares expected deposit root with actual deposit root
function stake32EthValidated(
bytes calldata pubkey,
bytes calldata signature,
bytes32 depositDataRoot,
bytes32 expectedDepositRoot
)
external
whenNotPaused
onlyLRTOperator
{
IBeaconDeposit depositContract = eigenPod.ethPOS();
bytes32 actualDepositRoot = depositContract.get_deposit_root();
if (expectedDepositRoot != actualDepositRoot) {
revert InvalidDepositRoot(expectedDepositRoot, actualDepositRoot);
}
IEigenPodManager eigenPodManager = IEigenPodManager(lrtConfig.getContract(LRTConstants.EIGEN_POD_MANAGER));
eigenPodManager.stake{ value: 32 ether }(pubkey, signature, depositDataRoot);

// tracks staked but unverified native ETH
stakedButUnverifiedNativeETH += 32 ether;

emit ETHStaked(pubkey, 32 ether);
Expand Down
9 changes: 9 additions & 0 deletions contracts/interfaces/IEigenPod.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,16 @@ library BeaconChainProofs {
}
}

interface IBeaconDeposit {
/// @notice Query the current deposit root hash.
/// @return The deposit root hash.
function get_deposit_root() external view returns (bytes32);
}

interface IEigenPod {
/// @notice This is the beacon chain deposit contract
function ethPOS() external returns (IBeaconDeposit);

/// @return delayedWithdrawalRouter address of eigenlayer delayedWithdrawalRouter,
/// which does book keeping of delayed withdrawls
function delayedWithdrawalRouter() external returns (address);
Expand Down
2 changes: 2 additions & 0 deletions contracts/interfaces/INodeDelegator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ interface INodeDelegator {
error StrategyIsNotSetForAsset();
error InvalidETHSender();
error InvalidRewardAmount();
error InvalidDepositRoot(bytes32 expectedDepositRoot, bytes32 actualDepositRoot);

// getter

function stakedButUnverifiedNativeETH() external view returns (uint256);

// methods
Expand Down
34 changes: 34 additions & 0 deletions test/integration/LRTNativeEthStakingIntegrationTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { NodeDelegator } from "contracts/NodeDelegator.sol";
import { LRTDepositPool } from "contracts/LRTDepositPool.sol";
import { UtilLib } from "contracts/utils/UtilLib.sol";
import { getLSTs } from "script/foundry-scripts/DeployLRT.s.sol";
import { IEigenPod, IBeaconDeposit } from "contracts/interfaces/IEigenPod.sol";

import { ITransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
Expand Down Expand Up @@ -198,6 +199,39 @@ contract LRTNativeEthStakingIntegrationTest is Test {
);
}

function test_stake32EthValidated() external returns (bytes32) {
// create eigen pod
vm.prank(manager);
nodeDelegator1.createEigenPod();

address eigenPod = address(nodeDelegator1.eigenPod());
// same eigenPod address should be created
assertEq(eigenPod, 0xf7483e448c1B94Ea557A53d99ebe7b4feE0c91df, "Wrong eigenPod address");

// stake 32 eth for validator1
bytes memory pubkey =
hex"8ff0088bf2bc73a41c74d1b1c6c997e4963ceffde55a09fef27596016d919b74b45372e8aa69fda5aac38a0c1a38dfd5";
bytes memory signature = hex"95e07ee28de0316ecdf9b528c222d81242898ee0095e284582bb453d331b7760"
hex"6d8dca23ab8980459ea8a9b9710e2f740fceb1a1c221a7fd75eb3ef4a6b68809"
hex"f3e76387f01f5d31718e6306375b20b29cb08d1374c7fb125d50c1b2f5a5cc0b";

bytes32 depositDataRoot = hex"6f30f44f0d8dada6ba5d8fd617c727020c01c697587d1a04ff6661be656198bc";

IBeaconDeposit depositContract = IEigenPod(eigenPod).ethPOS();
bytes32 expectedDepositRoot = depositContract.get_deposit_root();

vm.deal(address(nodeDelegator1), 32 ether);
uint256 balanceBefore = address(nodeDelegator1).balance;

vm.startPrank(operator);
nodeDelegator1.stake32EthValidated(pubkey, signature, depositDataRoot, expectedDepositRoot);

uint256 balanceAfter = address(nodeDelegator1).balance;
assertEq(balanceAfter, balanceBefore - 32 ether, "stake32eth unsuccesful");

return expectedDepositRoot;
}

function test_withdrawRewards() external {
// create eigen pod
vm.prank(manager);
Expand Down

0 comments on commit 630dc38

Please sign in to comment.