1
1
// SPDX-License-Identifier: MIT
2
2
pragma solidity ^ 0.8.27 ;
3
3
4
+ import {IEtherFiNode} from "../src/interfaces/IEtherFiNode.sol " ;
5
+ import {IEtherFiNodesManager} from "../src/interfaces/IEtherFiNodesManager.sol " ;
6
+ import {IRoleRegistry} from "../src/interfaces/IRoleRegistry.sol " ;
7
+ import {ILiquidityPool} from "../src/interfaces/ILiquidityPool.sol " ;
8
+
4
9
import {IDelegationManager} from "../src/eigenlayer-interfaces/IDelegationManager.sol " ;
10
+ import {IDelegationManagerTypes} from "../src/eigenlayer-interfaces/IDelegationManager.sol " ;
5
11
import {IEigenPodManager} from "../src/eigenlayer-interfaces/IEigenPodManager.sol " ;
6
12
import {IEigenPod} from "../src/eigenlayer-interfaces/IEigenPod.sol " ;
13
+ import {IStrategy} from "../src/eigenlayer-interfaces/IStrategy.sol " ;
7
14
import {BeaconChainProofs} from "../src/eigenlayer-libraries/BeaconChainProofs.sol " ;
8
- import {IERC20 } from "../lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol " ;
9
15
10
- import {IEtherFiNode} from "../src/interfaces/IEtherFiNode.sol " ;
11
- import {IEtherFiNodesManager} from "../src/interfaces/IEtherFiNodesManager.sol " ;
12
- import {IRoleRegistry} from "../src/interfaces/IRoleRegistry.sol " ;
13
- import {ILiquidityPool} from "../src/interfaces/ILiquidityPool.sol " ;
16
+ import {IERC20 } from "../lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol " ;
14
17
import {LibCall} from "../lib/solady/src/utils/LibCall.sol " ;
15
18
16
19
contract EtherFiNode is IEtherFiNode {
@@ -48,6 +51,8 @@ contract EtherFiNode is IEtherFiNode {
48
51
roleRegistry = IRoleRegistry (_roleRegistry);
49
52
}
50
53
54
+ fallback () external payable {}
55
+
51
56
//--------------------------------------------------------------------------------------
52
57
//---------------------------- Eigenlayer Interactions --------------------------------
53
58
//--------------------------------------------------------------------------------------
@@ -80,32 +85,42 @@ contract EtherFiNode is IEtherFiNode {
80
85
getEigenPod ().verifyCheckpointProofs (balanceContainerProof, proofs);
81
86
}
82
87
83
-
84
- /// @dev queue a withdrawal from eigenlayer. You must wait EIGENLAYER_WITHDRAWAL_DELAY_BLOCKS before claiming.
88
+ /// @dev convenience function to queue a beaconETH withdrawal from eigenlayer. You must wait EIGENLAYER_WITHDRAWAL_DELAY_BLOCKS before claiming.
85
89
/// It is fine to queue a withdrawal before validators have finished exiting on the beacon chain.
86
- function queueWithdrawal (IDelegationManager.QueuedWithdrawalParams calldata params ) external onlyAdmin returns (bytes32 withdrawalRoot ) {
90
+ function queueETHWithdrawal (uint256 amount ) external onlyAdmin returns (bytes32 withdrawalRoot ) {
91
+
92
+ // beacon eth is always 1 to 1 with deposit shares
93
+ uint256 [] memory depositShares = new uint256 [](1 );
94
+ depositShares[0 ] = amount;
95
+ IStrategy[] memory strategies = new IStrategy [](1 );
96
+ strategies[0 ] = IStrategy (address (0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0 ));
97
+
98
+ IDelegationManagerTypes.QueuedWithdrawalParams[] memory paramsArray = new IDelegationManagerTypes.QueuedWithdrawalParams [](1 );
99
+ paramsArray[0 ] = IDelegationManagerTypes.QueuedWithdrawalParams ({
100
+ strategies: strategies, // beacon eth
101
+ depositShares: depositShares,
102
+ __deprecated_withdrawer: address (this )
103
+ });
87
104
88
- // Implemented this way for convenience because we almost never queue multiple withdrawals at the same time
89
- IDelegationManager.QueuedWithdrawalParams[] memory paramsArray = new IDelegationManager.QueuedWithdrawalParams [](1 );
90
- paramsArray[0 ] = params;
91
105
return delegationManager.queueWithdrawals (paramsArray)[0 ];
92
106
}
93
107
94
- /// @dev completes all queued withdrawals that are currently claimable.
108
+
109
+ /// @dev completes all queued beaconETH withdrawals that are currently claimable.
95
110
/// Note that since the node is usually delegated to an operator,
96
111
/// most of the time this should be called with "receiveAsTokens" = true because
97
112
/// receiving shares while delegated will simply redelegate the shares.
98
- function completeQueuedWithdrawals (bool receiveAsTokens ) external onlyAdmin {
113
+ function completeQueuedETHWithdrawals (bool receiveAsTokens ) external onlyAdmin {
99
114
100
115
// because we are just dealing with beacon eth we don't need to populate the tokens[] array
101
- IERC20 [] memory tokens;
116
+ IERC20 [] memory tokens = new IERC20 []( 1 ) ;
102
117
103
118
(IDelegationManager.Withdrawal[] memory queuedWithdrawals , ) = delegationManager.getQueuedWithdrawals (address (this ));
104
119
for (uint256 i = 0 ; i < queuedWithdrawals.length ; i++ ) {
105
120
106
121
// skip this withdrawal if not enough time has passed
107
122
uint32 slashableUntil = queuedWithdrawals[i].startBlock + EIGENLAYER_WITHDRAWAL_DELAY_BLOCKS;
108
- if (uint32 (block .number ) > slashableUntil) continue ;
123
+ if (uint32 (block .number ) < slashableUntil) continue ;
109
124
110
125
delegationManager.completeQueuedWithdrawal (queuedWithdrawals[i], tokens, receiveAsTokens);
111
126
}
@@ -117,9 +132,26 @@ contract EtherFiNode is IEtherFiNode {
117
132
}
118
133
}
119
134
135
+ /// @dev queue a withdrawal from eigenlayer. You must wait EIGENLAYER_WITHDRAWAL_DELAY_BLOCKS before claiming.
136
+ /// For the general case of queuing a beaconETH withdrawal you can use queueETHWithdrawal instead.
137
+ function queueWithdrawals (IDelegationManager.QueuedWithdrawalParams[] calldata params ) external onlyAdmin returns (bytes32 [] memory withdrawalRoots ) {
138
+ return delegationManager.queueWithdrawals (params);
139
+ }
140
+
141
+ /// @dev complete an arbitrary withdrawal from eigenlayer.
142
+ /// For the general case of claiming beaconETH withdrawals you can use completeQueuedETHWithdrawals instead.
143
+ function completeQueuedWithdrawals (
144
+ IDelegationManager.Withdrawal[] calldata withdrawals ,
145
+ IERC20 [][] calldata tokens ,
146
+ bool [] calldata receiveAsTokens
147
+ ) external onlyAdmin {
148
+ delegationManager.completeQueuedWithdrawals (withdrawals, tokens, receiveAsTokens);
149
+ }
150
+
151
+
120
152
// @notice transfers any funds held by the node to the liquidity pool.
121
153
// @dev under normal operations it is not expected for eth to accumulate in the nodes,
122
- // this is just to handle any exceptional cases such as someone sending directly to the node.
154
+ // this is just to handle any exceptional cases such as someone sending directly to the node.
123
155
function sweepFunds () external onlyAdmin {
124
156
(bool sent , ) = payable (address (liquidityPool)).call {value: address (this ).balance, gas: 20000 }("" );
125
157
if (! sent) revert TransferFailed ();
0 commit comments