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
SSV Native staking #2015
base: master
Are you sure you want to change the base?
SSV Native staking #2015
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2015 +/- ##
==========================================
+ Coverage 60.92% 62.24% +1.31%
==========================================
Files 58 64 +6
Lines 2974 3181 +207
Branches 774 829 +55
==========================================
+ Hits 1812 1980 +168
- Misses 1159 1198 +39
Partials 3 3 ☔ View full report in Codecov by Sentry. |
EXIT_COMPLETE // validator has funds withdrawn to the EigenPod and is removed from the SSV | ||
} | ||
|
||
event RegistratorAddressChanged(address oldAddress, address newAddress); |
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 know this has been a pattern used for a while in Origin dollar, but do you need both the old and new addresses in change events? Can we just have the new address?
contracts/contracts/strategies/NativeStaking/NativeStakingSSVStrategy.sol
Outdated
Show resolved
Hide resolved
|
||
balance = activeDepositedValidators * 32 ether; | ||
balance += beaconChainRewardWETH; | ||
balance += FEE_ACCUMULATOR_ADDRESS.balance; |
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 don't think we want to include the MEV rewards in the FeeAccumulator if those are going to be harvested and sent to through the dripper.
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.
Thanks this is a nice catch. I see I haven't given it enough though as to how (W)ETH should be handled.
Lets continue discussion here so we have it all in 1 place: https://www.notion.so/originprotocol/How-should-accounting-function-handle-ETH-after-accounting-4ed3a9352c0f4fc8aa6bb866022a25cb
contracts/contracts/strategies/NativeStaking/ValidatorAccountant.sol
Outdated
Show resolved
Hide resolved
/// @dev Governor that can manually correct the accounting | ||
address public accountingGovernor; | ||
/// @dev Strategist that can pause the accounting | ||
address public strategist; |
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.
Best to read the strategist
from the Vault rather than duplicating the maintenance in the strategy. This is what OETH AMO strategy does
modifier onlyStrategist() {
require(
msg.sender == IVault(vaultAddress).strategistAddr(),
"Caller is not the Strategist"
);
_;
}
* Update Natspec * Generated docs for native eth strategy * Prettier and linter Fixed spelling of ValidatorAccountant events Implemented depositSSV * Updated Natspec Moved MAX_STAKE on ValidatorAccountant to a constant * Removed strategist from strategy as its already maintained in the Vault * Fix compilation error * Fix unit tests * fix linter
* Added OETH process diagram with functions calls for native staking * Native Staking Strategy now hold consensus rewards at ETH FeeAccumulator now holds execution rewards as ETH Removed WETH immutable from FeeAccumulator Converted custom errors back to require with string collect rewards now converts ETH to WETH at harvest checkBalance is now validators * 32 plus WETH balance from deposits Renamed beaconChainRewardsWETH to consensusRewards Fixed bug in stakeETH that was converting all WETH to ETH
* Fixed native staking deployment since the strategist is got from the vault * Refactor of some Native Staking events Refactor of Native Staking unit tests * Renamed AccountingBeaconChainRewards to AccountingConsensusRewards Accounting updated to handle zero ETH from the beacon chain * fixed bug not accounting for previous consensus rewards Blow fuse if ETH balance < previous consensus rewards * Pause collectRewardTokens and doAccounting on accounting failure. Validated asset on deposit to Native Staking Strategy. Moved depositSSV from NativeStakingSSVStrategy to ValidatorRegistrator moved onlyStrategist modified and VAULT_ADDRESS immutable from ValidatorAccountant to ValidatorRegistrator manuallyFixAccounting changed to use whenPaused modifier made fuseIntervalEnd inclusive Natspec updates refactoring of native staking unit tests
* add basic steps to deploy OETH to holesky * prettier * minor change * holesky deployment ifles holesky deployment files * add holesky deployment files * minor fix * minor fixes * make the fork tests run on Holesky * add some more tests * testing SSV staking on Holesky * refactor where deployment files are located * more progress on deployment * add deposit to validator deployment files * remove log * prettier * lint * move file * SSV cluster info (#2036) * add ability to fetch SSV cluster information * prettier
* manuallyFixAccounting now uses delta values and only callable by the strategist manuallyFixAccounting calls doAccounting to check the fuse is still not blown Removed accountingGovernor * Added pauseOnFail param to internal _doAccounting Increased the allowed delta values of manuallyFixAccounting * ran prettier
uint256 public constant MAX_STAKE = 32 ether; | ||
|
||
/// @notice Keeps track of the total consensus rewards swept from the beacon chain | ||
uint256 public consensusRewards = 0; |
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 Solidity, variables are automatically initialized to zero. Therefore, explicitly initializing variables to zero is not mandatory and can be skipped.
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 point, fixed here: 8bf9a26
validators[i].depositDataRoot | ||
); | ||
|
||
activeDepositedValidators += 1; |
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 could save on some gas by adding the validators.length
once instead of doing a +1 on every interaction..
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.
great gas savings thanks: fd4f2d2
|
||
// send the ETH that is from fully withdrawn validators to the Vault | ||
if (newSweptETH >= MAX_STAKE) { | ||
uint256 fullyWithdrawnValidators = newSweptETH / MAX_STAKE; |
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 safe division could use unchecked
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.
agreed, thanks
require(msg.sender == STRATEGY, "Caller is not the Strategy"); | ||
|
||
eth = address(this).balance; | ||
if (eth > 0) { |
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 have a couple of superior to zero checks, it's more gas-efficient to use a not zero check.
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 tested this with the hardhat-gas-reporter and Remix and didn't see a noticeable difference in gas usage.
IWETH9(WETH_TOKEN_ADDRESS).withdraw(requiredETH); | ||
|
||
// For each validator | ||
for (uint256 i = 0; i < validators.length; ) { |
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.
validators.length
should be cached outside of the loop.
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.
thanks, fixed here: fd4f2d2
97e38ec
to
fe12d23
Compare
* adding defender action task * fix unit tests setup * update the registrator address of the native staking contract * fix up the operate validators script so that it works for native staking on holesky * also add the gitignore * add ability to exit if staking contract is paused
* Fixed resolveAsset * Fixed validator fork tests Added error func sigs to ISSVNetwork * Fixed harvester behaviour tests * Fix global hooks * Fix tooling --------- Co-authored-by: Shahul Hameed <10547529+shahthepro@users.noreply.github.com>
* add payable to fee accumulator * remove zero initializers * some gas savings
Contracts
Changes
NativeStakingSSVStrategy
that takes WETH from the Vault and stakes ETH into SSV validators.FeeAccumulator
to receive ETH execution rewards.BaseHarvester
so it can collect WETH and send it straight to theDripper
Diagrams
NativeStakingSSVStrategy
FeeAccumulator
Processes
Value Flows
The flow of native currency (ETH) and tokens between the wallets and contracts.
Contract calls
Testing
Unit Tests
Unit tests are in
contracts/test/strategies/nativeSSVStaking.js
yarn run test
Holesky fork tests
Holesky fork tests are in
contracts/test/strategies/nativeSsvStaking.holesky.fork-test.js
Mainnet fork tests
Mainnet fork tests are in
contracts/test/strategies/nativeSsvStaking.fork-test.js
Deployment
Operations
Hardhat tasks