Skip to content

Commit

Permalink
Merge branch 'master' into feat/commit-linting
Browse files Browse the repository at this point in the history
  • Loading branch information
steven committed Oct 27, 2023
2 parents 8302af0 + 244a39d commit b8f1166
Show file tree
Hide file tree
Showing 58 changed files with 970 additions and 1,839 deletions.
4 changes: 2 additions & 2 deletions docs/core/DelegationManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ Called by the `EigenPodManager` when a Staker's shares decrease. This method is
* `EigenPod.verifyAndProcessWithdrawals`

*Effects*: If the Staker in question is delegated to an Operator, the Operator's delegated balance for the `strategy` is decreased by `shares`
* This method is a no-op if the Staker is not delegated an an Operator.
* This method is a no-op if the Staker is not delegated to an Operator.

*Requirements*:
* Caller MUST be either the `StrategyManager` or `EigenPodManager` (although the `StrategyManager` doesn't use this method)
Expand All @@ -403,4 +403,4 @@ Allows the `owner` to update the number of blocks that must pass before a withdr

*Requirements*:
* Caller MUST be the `owner`
* `_withdrawalDelayBlocks` MUST NOT be greater than `MAX_WITHDRAWAL_DELAY_BLOCKS` (50400)
* `_withdrawalDelayBlocks` MUST NOT be greater than `MAX_WITHDRAWAL_DELAY_BLOCKS` (50400)
14 changes: 4 additions & 10 deletions docs/core/EigenPod.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The EigenPods subprotocol is a protocol within the broader EigenLayer protocol t

The purpose of this document is to detail the EigenPods subprotocol's functionality since it is complex and not well documented besides the (not so) "self documenting code". In addition, there are some proposed revisions that are to be considered.

Ultimately, the protocol's values are security, functionality, and simplicity. Security means no loss of user funds, no unforseen scenarios for AVSs, and more. Functionality means that the protocol is acheiving its goals with respected to its expected function to the best of its ability (see [functionality goals](#Functionality-Goals) for more). Simplicity means ease of understanding for stakers and AVSs, ease of integration for AVSs, and more confidence in the protocol's security.
Ultimately, the protocol's values are security, functionality, and simplicity. Security means no loss of user funds, no unforeseen scenarios for AVSs, and more. Functionality means that the protocol is achieving its goals with respect to its expected function to the best of its ability (see [functionality goals](#Functionality-Goals) for more). Simplicity means ease of understanding for stakers and AVSs, ease of integration for AVSs, and more confidence in the protocol's security.

## Challenges
The reasons native restaking is more complex than token restaking are
Expand All @@ -30,17 +30,11 @@ Since the execution layer cannot yet synchronously read arbitrary state from the

This will either be implemented by Succinct Labs or eventually by Ethereum natively in EIP-4788 ([read here](https://eips.ethereum.org/EIPS/eip-4788)). The interface will have requests be for a block number and responses be the block roots corresponding to the provided block numbers.

### Hysteresis

We want to understimate validator balances on EigenLayer to be tolerant to small slashing events that occur on the beacon chain.

We underestimate validator stake on EigenLayer through the following equation: $\text{eigenlayerBalance} = \text{min}(32, \text{floor}(x-C))$ where $C$ is some offset which we can assume is equal to 0.75. Since a validator's effective balance on the beacon chain can at most 0.25 ETH more than its actual balance on the beacon chain, we subtract 0.75 and floor it for simplicity.

### Creating EigenPods

Any user that wants to participate in native restaking first deploys an EigenPod contract by calling `createPod()` on the EigenPodManager. This deploys an EigenPod contract which is a BeaconProxy in the Beacon Proxy pattern. The user is called the *pod owner* of the EigenPod they deploy.

### Repointing Withdrawan Credentials: BLS to Execution Changes and Deposits
### Repointing Withdrawal Credentials: BLS to Execution Changes and Deposits

The precise method by which native restaking occurs is a user repointing their validator's withdrawal credentials. Once an EigenPod is created, a user can make deposits for new validators or switch the withdrawal credentials of their existing validators to their EigenPod address. This makes it so that all funds that are ever withdrawn from the beacon chain on behalf of their validators will be sent to their EigenPod. Since the EigenPod is a contract that runs code as part of the EigenLayer protocol, we engineer it in such a way that the funds that can/will flow through it are restaked on EigenLayer.

Expand All @@ -58,7 +52,7 @@ We will take a brief aside to explain a simpler part of the protocol, partial wi

Note that partial withdrawals can be withdrawn immediately from the system because they are not staked on EigenLayer, unlike the base validator stake that is restaked on EigenLayer

Currently, users can submit partial withdrawal proofs one at a time, at a cost of around 30-40k gas per proof. This is highly inefficient as partial withdrawals are often nominal amounts for which an expensive proof transaction each time is not feasible for our users. The solution is to use succinct zk proving solution generate a single proof for multiple withdrawals, which can be verified for a fixed cost of around 300k gas. This system and associated integration are currently under development.
Currently, users can submit partial withdrawal proofs one at a time, at a cost of around 30-40k gas per proof. This is highly inefficient as partial withdrawals are often nominal amounts for which an expensive proof transaction each time is not feasible for our users. The solution is to use succinct zk proving solution to generate a single proof for multiple withdrawals, which can be verified for a fixed cost of around 300k gas. This system and associated integration are currently under development.


### Proofs of Validator Balance Updates
Expand All @@ -75,5 +69,5 @@ Full withdrawals occur when a validator completely exits and withdraws from the

If the amount of the withdrawal was greater than what the validator has reestaked on EigenLayer (which most often will be), then the excess is immediately sent to the DelayedWithdrawalRouter to be sent to the pod owner, as this excess balance is not restaked.

Once the "restaked balance" of the pod is incremented, the pod owner is able to queue withdrawals for up to the "restaked balance", decrementing the "restaked balance" by the withdrawal amount. When the withdrawal is completed the pod simply sends a payment to the pod owner for the queued funds. Note that if the withdrawer chooses to recieve the withdrawal as shares, the StrategyManager will increase the "restaked balance" by the withdrawal amount.
Once the "restaked balance" of the pod is incremented, the pod owner is able to queue withdrawals for up to the "restaked balance", decrementing the "restaked balance" by the withdrawal amount. When the withdrawal is completed the pod simply sends a payment to the pod owner for the queued funds. Note that if the withdrawer chooses to receive the withdrawal as shares, the StrategyManager will increase the "restaked balance" by the withdrawal amount.

12 changes: 2 additions & 10 deletions docs/core/EigenPodManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The functions of the `EigenPodManager` and `EigenPod` contracts are tightly link
* `validatorStatus`: (`INACTIVE`, `ACTIVE`, `WITHDRAWN`)
* `validatorIndex`: A `uint40` that is unique for each validator making a successful deposit via the deposit contract
* `mostRecentBalanceUpdateTimestamp`: A timestamp that represents the most recent successful proof of the validator's effective balance
* `restakedBalanceGwei`: Calculated against the validator's proven effective balance using `_calculateRestakedBalanceGwei` (see definitions below)
* `restakedBalanceGwei`: set to the validator's balance.
* `withdrawableRestakedExecutionLayerGwei`: When a Staker proves that a validator has exited from the beacon chain, the withdrawal amount is added to this variable. When completing a withdrawal of beacon chain ETH, the withdrawal amount is subtracted from this variable. See also:
* [`DelegationManager`: "Undelegating and Withdrawing"](./DelegationManager.md#undelegating-and-withdrawing)
* [`EigenPodManager`: "Withdrawal Processing"](#withdrawal-processing)
Expand All @@ -58,14 +58,6 @@ The functions of the `EigenPodManager` and `EigenPod` contracts are tightly link
* Pod Owners can delegate their `EigenPodManager` shares to Operators (via `DelegationManager`).
* These shares correspond to the amount of provably-restaked beacon chain ETH held by the Pod Owner via their `EigenPod`.
* `EigenPod`:
* `_calculateRestakedBalanceGwei(uint64 effectiveBalance) -> (uint64)`:
* This method is used by an `EigenPod` to calculate a "pessimistic" view of a validator's effective balance to avoid the need for repeated balance updates when small balance fluctuations occur.
* The calculation subtracts an offset (`RESTAKED_BALANCE_OFFSET_GWEI`) from the validator's proven balance, and round down to the nearest ETH
* Related: `uint64 RESTAKED_BALANCE_OFFSET_GWEI`
* As of M2, this is 0.75 ETH (in Gwei)
* Related: `uint64 MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR`
* As of M2, this is 31 ETH (in Gwei)
* This is the maximum amount of restaked ETH a single validator can be credited with in EigenLayer
* `_podWithdrawalCredentials() -> (bytes memory)`:
* Gives `abi.encodePacked(bytes1(uint8(1)), bytes11(0), address(EigenPod))`
* These are the `0x01` withdrawal credentials of the `EigenPod`, used as a validator's withdrawal credentials on the beacon chain.
Expand Down Expand Up @@ -192,7 +184,7 @@ For each validator the Pod Owner wants to verify, the Pod Owner must supply:
* `VALIDATOR_STATUS` moves from `INACTIVE` to `ACTIVE`
* `validatorIndex` is recorded
* `mostRecentBalanceUpdateTimestamp` is set to the `oracleTimestamp` used to fetch the beacon block root
* `restakedBalanceGwei` is set to `_calculateRestakedBalanceGwei(effectiveBalance)`
* `restakedBalanceGwei` is set to the validator's effective balance
* See [`EigenPodManager.recordBeaconChainETHBalanceUpdate`](#eigenpodmanagerrecordbeaconchainethbalanceupdate)

*Requirements*:
Expand Down
2 changes: 1 addition & 1 deletion docs/core/proofs/BeaconChainProofs.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function verifyStateRootAgainstLatestBlockRoot(
bytes calldata stateRootProof
) internal
```
Verifies the proof of a beacon state root against the oracle provded block root. Every [beacon block](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblock) in the beacon state contains the state root corresponding with that block. Thus to prove anything against a state root, we must first prove the state root against the corresponding oracle block root.
Verifies the proof of a beacon state root against the oracle provided block root. Every [beacon block](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblock) in the beacon state contains the state root corresponding with that block. Thus to prove anything against a state root, we must first prove the state root against the corresponding oracle block root.

![Verify State Root Proof Structure](../../images/staterootproof.png)

Expand Down
8 changes: 1 addition & 7 deletions script/M1_Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ contract Deployer_M1 is Script, Test {
// IMMUTABLES TO SET
uint256 REQUIRED_BALANCE_WEI;
uint256 MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR;
uint256 EFFECTIVE_RESTAKED_BALANCE_OFFSET_GWEI;
uint64 GOERLI_GENESIS_TIME = 1616508000;

// OTHER DEPLOYMENT PARAMETERS
Expand Down Expand Up @@ -123,10 +122,6 @@ contract Deployer_M1 is Script, Test {
config_data,
".eigenPod.MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR"
);
EFFECTIVE_RESTAKED_BALANCE_OFFSET_GWEI = stdJson.readUint(
config_data,
".eigenPod.EFFECTIVE_RESTAKED_BALANCE_OFFSET_GWEI"
);

// tokens to deploy strategies for
StrategyConfig[] memory strategyConfigs;
Expand Down Expand Up @@ -189,7 +184,6 @@ contract Deployer_M1 is Script, Test {
delayedWithdrawalRouter,
eigenPodManager,
uint64(MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR),
uint64(EFFECTIVE_RESTAKED_BALANCE_OFFSET_GWEI),
GOERLI_GENESIS_TIME
);

Expand Down Expand Up @@ -541,7 +535,7 @@ contract Deployer_M1 is Script, Test {
// "strategyManager: withdrawalDelayBlocks initialized incorrectly");
// require(delayedWithdrawalRouter.withdrawalDelayBlocks() == 7 days / 12 seconds,
// "delayedWithdrawalRouter: withdrawalDelayBlocks initialized incorrectly");
// uint256 REQUIRED_BALANCE_WEI = 31 ether;
// uint256 REQUIRED_BALANCE_WEI = 32 ether;

require(
strategyManager.strategyWhitelister() == operationsMultisig,
Expand Down
3 changes: 1 addition & 2 deletions script/M1_deploy.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
{
"PARTIAL_WITHDRAWAL_FRAUD_PROOF_PERIOD_BLOCKS": 50400,
"REQUIRED_BALANCE_WEI": "31000000000000000000",
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": "31000000000",
"EFFECTIVE_RESTAKED_BALANCE_OFFSET_GWEI": "750000000"
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": "31000000000"
},
"eigenPodManager":
{
Expand Down
2 changes: 1 addition & 1 deletion script/configs/AVSContractsDeploy.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"eigenPod":
{
"PARTIAL_WITHDRAWAL_FRAUD_PROOF_PERIOD_BLOCKS": 50400,
"REQUIRED_BALANCE_WEI": "31000000000000000000"
"REQUIRED_BALANCE_WEI": "32000000000000000000"
},
"eigenPodManager":
{
Expand Down
2 changes: 1 addition & 1 deletion script/configs/M1_deploy_devnet.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"eigenPod":
{
"PARTIAL_WITHDRAWAL_FRAUD_PROOF_PERIOD_BLOCKS": 50400,
"REQUIRED_BALANCE_WEI": "31000000000000000000"
"REQUIRED_BALANCE_WEI": "32000000000000000000"
},
"eigenPodManager":
{
Expand Down
2 changes: 1 addition & 1 deletion script/configs/M1_deploy_mainnet.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"eigenPod":
{
"PARTIAL_WITHDRAWAL_FRAUD_PROOF_PERIOD_BLOCKS": 50400,
"REQUIRED_BALANCE_WEI": "31000000000000000000"
"REQUIRED_BALANCE_WEI": "32000000000000000000"
},
"eigenPodManager":
{
Expand Down
4 changes: 1 addition & 3 deletions script/middleware/DeployOpenEigenLayer.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,7 @@ contract DeployOpenEigenLayer is Script, Test {
delayedWithdrawalRouter,
eigenPodManager,
// uint64(MAX_VALIDATOR_BALANCE_GWEI),
uint64(31 gwei),
// uint64(EFFECTIVE_RESTAKED_BALANCE_OFFSET_GWEI)
uint64(0.75 gwei),
uint64(32 gwei),
1000 // temp genesis time
);

Expand Down
3 changes: 1 addition & 2 deletions script/milestone/M2Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,7 @@ contract M2Deploy is Script, Test {
_ethPOS: ethPOS,
_delayedWithdrawalRouter: delayedWithdrawalRouter,
_eigenPodManager: eigenPodManager,
_MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR: 31 gwei,
_RESTAKED_BALANCE_OFFSET_GWEI: 0.5 gwei,
_MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR: 32 gwei,
_GENESIS_TIME: 1616508000
});

Expand Down
3 changes: 1 addition & 2 deletions script/milestone/M2Deploy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ contract M2Deploy is Script, Test {
_ethPOS: ethPOS,
_delayedWithdrawalRouter: delayedWithdrawalRouter,
_eigenPodManager: eigenPodManager,
_MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR: 31 gwei,
_RESTAKED_BALANCE_OFFSET_GWEI: 0.5 gwei,
_MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR: 32 gwei,
_GENESIS_TIME: 1616508000
});

Expand Down
7 changes: 2 additions & 5 deletions script/testing/M2_Deploy_From_Scratch.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ contract Deployer_M2 is Script, Test {

// IMMUTABLES TO SET
uint64 MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR;
uint64 RESTAKED_BALANCE_OFFSET_GWEI;
uint64 GOERLI_GENESIS_TIME = 1616508000;

// OTHER DEPLOYMENT PARAMETERS
Expand Down Expand Up @@ -121,7 +120,6 @@ contract Deployer_M2 is Script, Test {
MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR = uint64(
stdJson.readUint(config_data, ".eigenPod.MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR")
);
RESTAKED_BALANCE_OFFSET_GWEI = uint64(stdJson.readUint(config_data, ".eigenPod.RESTAKED_BALANCE_OFFSET_GWEI"));

// tokens to deploy strategies for
StrategyConfig[] memory strategyConfigs;
Expand Down Expand Up @@ -184,7 +182,6 @@ contract Deployer_M2 is Script, Test {
delayedWithdrawalRouter,
eigenPodManager,
MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR,
RESTAKED_BALANCE_OFFSET_GWEI,
GOERLI_GENESIS_TIME
);

Expand Down Expand Up @@ -540,9 +537,9 @@ contract Deployer_M2 is Script, Test {
// "strategyManager: withdrawalDelayBlocks initialized incorrectly");
// require(delayedWithdrawalRouter.withdrawalDelayBlocks() == 7 days / 12 seconds,
// "delayedWithdrawalRouter: withdrawalDelayBlocks initialized incorrectly");
// uint256 MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR = 31 ether;
// uint256 MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR = 32 ether;
require(
eigenPodImplementation.MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR() == 31 gwei,
eigenPodImplementation.MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR() == 32 gwei,
"eigenPod: MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR initialized incorrectly"
);

Expand Down
3 changes: 1 addition & 2 deletions script/testing/M2_deploy_from_scratch.anvil.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
},
"eigenPod": {
"PARTIAL_WITHDRAWAL_FRAUD_PROOF_PERIOD_BLOCKS": 1,
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": "31000000000",
"RESTAKED_BALANCE_OFFSET_GWEI": "750000000"
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": "32000000000"
},
"eigenPodManager": {
"max_pods": 0,
Expand Down
4 changes: 1 addition & 3 deletions script/testing/M2_deploy_from_scratch.mainnet.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@
"eigenPod":
{
"PARTIAL_WITHDRAWAL_FRAUD_PROOF_PERIOD_BLOCKS": 50400,
"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": "31000000000",
"RESTAKED_BALANCE_OFFSET_GWEI": "750000000"

"MAX_RESTAKED_BALANCE_GWEI_PER_VALIDATOR": "32000000000"
},
"eigenPodManager":
{
Expand Down
1 change: 0 additions & 1 deletion script/upgrade/GoerliUpgrade1.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ contract GoerliUpgrade1 is Script, Test {
delayedWithdrawalRouter,
eigenPodManager,
32e9,
75e7,
1616508000
)
);
Expand Down
Loading

0 comments on commit b8f1166

Please sign in to comment.