-
Notifications
You must be signed in to change notification settings - Fork 91
OZ C-01 - Postponed Pending Deposit Breaks verifyDeposit and verifyBalances #2622
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
Conversation
Added verifyBalancesWithDeposits that can only be called by the staking monitor
…ee proofs verifyDeposit now checks the first pending deposit is not to an exiting validator
Updated Natspec with maths on calculating the gen indexes Removed the staking monitor
Added amountWei to the DepositValidatorExiting event
// Verify the withdrawableEpoch on the validator of the strategy's deposit | ||
IBeaconProofs(BEACON_PROOFS).verifyValidatorWithdrawable( | ||
depositBlockRoot, | ||
validatorData.index, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we verify Index here do we have a need for a separate verifyValidator
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function could promote a validator from STAKED to VERIFIED and add an entry to verifiedValidators
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a few options:
- Consolidate
verifyValidator
intoverifyDeposit
- Add the validatorIndex to the mapping of the validator pub key hash
- Iterate over the verifiedDeposits to get the validator index in
verifiedValidators
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've gone with option 2 which means I don't need to pass in the validator index or pubKeyProof in strategyValidatorData
See commit 93b398b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably the commit the comment was referring to: 7ee0a4d
contracts/contracts/strategies/NativeStaking/CompoundingValidatorManager.sol
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few comments. Great job on these changes aside from 2 issues I think they are solid
contracts/contracts/strategies/NativeStaking/CompoundingValidatorManager.sol
Outdated
Show resolved
Hide resolved
contracts/contracts/strategies/NativeStaking/CompoundingValidatorManager.sol
Outdated
Show resolved
Hide resolved
contracts/contracts/strategies/NativeStaking/CompoundingValidatorManager.sol
Show resolved
Hide resolved
contracts/contracts/strategies/NativeStaking/CompoundingValidatorManager.sol
Show resolved
Hide resolved
contracts/contracts/strategies/NativeStaking/CompoundingValidatorManager.sol
Outdated
Show resolved
Hide resolved
contracts/contracts/strategies/NativeStaking/CompoundingValidatorManager.sol
Outdated
Show resolved
Hide resolved
// If there are no deposits then we can skip the deposit verification | ||
// This section is after the validator balance verifications so an exited validator will be marked | ||
// as EXITED before the deposits are verified. If there was a deposit to an exited validator | ||
// then the deposit can only be removed once the validator is fully exited. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit comment addition:
... validator is fully exited. The ETH deposited to an exiting validator remains in the beaconState.pendingDeposits
as part of the beacon chain's deposits_to_postpone
array inside which the deposit remains as long as the validator has not fully exited from the beacon chain. Once the validator has fully exited the postponed deposit is credited back to the strategy contract.
contracts/contracts/strategies/NativeStaking/CompoundingValidatorManager.sol
Show resolved
Hide resolved
// now has to wait until the validator's balance is verified to be zero. | ||
require( | ||
firstPendingDeposit.slot < depositData.slot || | ||
verificationEpoch < depositData.withdrawableEpoch || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 in StakeEth the depositData.withdrawableEpoch
is set to FAR_FUTURE_EPOCH. This means if verify deposit has not been called yet on a withdrawable validator the verificationEpoch < depositData.withdrawableEpoch
check will always be true and make this whole require pass.
I think this require should look like this:
require(
firstPendingDeposit.slot < depositData.slot ||
(
verificationEpoch < depositData.withdrawableEpoch &&
depositData.withdrawableEpoch != FAR_FUTURE_EPOCH
) ||
validatorState[depositData.pubKeyHash] ==
VALIDATOR_STATE.EXITED,
"Deposit likely processed"
);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good spot. Yes, the logic was wrong. It was meant to be
// Check the stored deposit is still waiting to be processed on the beacon chain.
// That is, the first pending deposit slot is before the slot of the staking strategy's deposit.
// If the deposit has been processed, it will need to be verified with `verifyDeposit`.
// OR the deposit is to an exiting validator so check it is still not withdrawable.
// If the validator is not withdrawable, then the deposit can not have been processed yet.
// If the validator is now withdrawable, then the deposit may have been processed. The strategy
// now has to wait until the validator's balance is verified to be zero.
require(
firstPendingDeposit.slot < depositData.slot ||
(validatorState[depositData.pubKeyHash] ==
VALIDATOR_STATE.EXITED &&
verificationEpoch < depositData.withdrawableEpoch),
"Deposit likely processed"
);
Fixed in 93b398b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice that is cleaner and simpler than my suggestion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this 2 possible implementations of require won't the latter block the verifyBalances
until the validator that has been deposited to and is exiting has fully exited? While the former would allow for passing of verifyBalances
even if the validator is exiting and the snapshot has been done before its withdrawable epoch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct. I've fixed with commit 78e29f1
Added more beacon proof unit tests
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## nicka/pectra #2622 +/- ##
================================================
+ Coverage 40.54% 40.61% +0.06%
================================================
Files 121 121
Lines 5628 5666 +38
Branches 1494 1502 +8
================================================
+ Hits 2282 2301 +19
- Misses 3344 3363 +19
Partials 2 2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Changes
verifyDeposit
:verifyBalances
:EXITED
Code Change Checklist
To be completed before internal review begins:
Internal review:
Deploy checklist
Two reviewers complete the following checklist: