Skip to content

Commit efe3234

Browse files
committed
Implement capital distribution process
1 parent 5bcd271 commit efe3234

17 files changed

Lines changed: 697 additions & 101 deletions

contracts/contract/dao/protocol/settings/RocketDAOProtocolSettingsMegapool.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ contract RocketDAOProtocolSettingsMegapool is RocketDAOProtocolSettings, RocketD
2121
function initialise() override public {
2222
// Set defaults
2323
_setSettingUint("megapool.time.before.dissolve", 2 weeks); // 2 weeks (RPIP-59)
24+
_setSettingUint("maximum.megapool.eth.penalty", 612 ether); // RPIP-42
2425
// Update deploy flag
2526
require (!getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed"))), "Already initialised");
2627
setBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")), true);
@@ -36,6 +37,10 @@ contract RocketDAOProtocolSettingsMegapool is RocketDAOProtocolSettings, RocketD
3637
if (settingKey == keccak256(abi.encodePacked("megapool.time.before.dissolve"))) {
3738
// TODO: No guardrail is specified in RPIP-59 but there should probably be a minimum?
3839
require(_value >= 48 hours, "Time must be greater than 48 hours");
40+
} else if (settingKey == keccak256(abi.encodePacked("maximum.megapool.eth.penalty"))) {
41+
// Per RPIP-42
42+
// TODO: This is a placeholder value
43+
require(_value <= 300 ether, "Penalty must equal or exceed 300 ETH");
3944
}
4045
}
4146
// Update setting now

contracts/contract/deposit/RocketDepositPool.sol

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,13 +480,11 @@ contract RocketDepositPool is RocketBase, RocketDepositPoolInterface, RocketVaul
480480
linkedListStorage.removeItem(namespace, key);
481481
// Perform balance accounting
482482
subUint(keccak256("deposit.pool.requested.total"), value.requestedValue * milliToWei);
483-
// Add to node's credit for the amount supplied
484-
RocketMegapoolDelegateInterface megapool = RocketMegapoolDelegateInterface(msg.sender);
485-
address nodeAddress = megapool.getNodeAddress();
486-
addUint(keccak256(abi.encodePacked("node.deposit.credit.balance", nodeAddress)), value.suppliedValue * milliToWei);
487483
if (_expressQueue) {
488484
// Refund express ticket
485+
RocketMegapoolDelegateInterface megapool = RocketMegapoolDelegateInterface(msg.sender);
489486
RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
487+
address nodeAddress = megapool.getNodeAddress();
490488
rocketNodeManager.refundExpressTicket(nodeAddress);
491489
// Update head moved block
492490
if (isAtHead) {
@@ -502,6 +500,13 @@ contract RocketDepositPool is RocketBase, RocketDepositPoolInterface, RocketVaul
502500
emit QueueExited(msg.sender, block.timestamp);
503501
}
504502

503+
function applyCredit(uint256 _amount) external onlyRegisteredMegapool(msg.sender) {
504+
// Add to node's credit for the amount supplied
505+
RocketMegapoolDelegateInterface megapool = RocketMegapoolDelegateInterface(msg.sender);
506+
address nodeAddress = megapool.getNodeAddress();
507+
addUint(keccak256(abi.encodePacked("node.deposit.credit.balance", nodeAddress)), _amount);
508+
}
509+
505510
/// @notice Allows node operator to withdraw any ETH credit they have as rETH
506511
/// @param _amount Amount in ETH to withdraw
507512
function withdrawCredit(uint256 _amount) override external onlyRegisteredNode(msg.sender) {

contracts/contract/megapool/RocketMegapoolDelegate.sol

Lines changed: 195 additions & 33 deletions
Large diffs are not rendered by default.

contracts/contract/megapool/RocketMegapoolStorageLayout.sol

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,18 @@ abstract contract RocketMegapoolStorageLayout {
2727
uint32 lastAssignmentTime; // Timestamp of when the last fund assignment took place
2828
uint32 lastRequestedValue; // Value in milliether last requested
2929
uint32 lastRequestedBond; // Value in milliether of the bond supplied for last request for funds
30+
uint32 depositValue; // Total amount deposited to beaconchain in gwei
3031

3132
bool staked; // Whether the validator has staked the minimum required to begin validating (32 ETH)
3233
bool exited; // Whether the validator has exited the beacon chain
3334
bool inQueue; // Whether the validator is currently awaiting funds from the deposit pool
3435
bool inPrestake; // Whether the validator is currently awaiting the stake operation
3536
bool expressUsed; // Whether the last request for funds consumed an express ticket
3637
bool dissolved; // Whether the validator failed to prestake their initial deposit in time
38+
bool exiting; // Whether the validator is queued to exit on the beaconchain
39+
40+
uint64 validatorIndex; // Index of the validator on the beaconchain
41+
uint64 exitBalance; // Final balance of the validator at withdrawable_epoch in gwei (amount returned to EL)
3742
}
3843

3944
// Extra data temporarily stored for prestake operation
@@ -68,7 +73,6 @@ abstract contract RocketMegapoolStorageLayout {
6873
uint256 internal nodeRewards; // Unclaimed ETH rewards for the owner
6974

7075
uint256 internal nodeBond; // Total value of bond supplied by node operator
71-
uint256 internal nodeCapital; // Value of capital on the beacon chain supplied by the owner
7276
uint256 internal userCapital; // Value of capital on the beacon chain supplied by the DP
7377

7478
uint256 internal debt; // Amount the owner owes the DP
@@ -77,4 +81,7 @@ abstract contract RocketMegapoolStorageLayout {
7781

7882
mapping(uint32 => ValidatorInfo) internal validators;
7983
mapping(uint32 => PrestakeData) internal prestakeData;
84+
85+
uint32 internal numExitingValidators;
86+
uint32 internal soonestWithdrawableEpoch;
8087
}

contracts/contract/node/RocketNodeDeposit.sol

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,17 @@ pragma solidity 0.8.18;
33

44
import {RocketStorageInterface} from "../../interface/RocketStorageInterface.sol";
55
import {RocketVaultInterface} from "../../interface/RocketVaultInterface.sol";
6-
import {RocketDAOProtocolSettingsMinipoolInterface} from "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsMinipoolInterface.sol";
6+
import {RocketVaultWithdrawerInterface} from "../../interface/RocketVaultWithdrawerInterface.sol";
77
import {RocketDAOProtocolSettingsNodeInterface} from "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol";
88
import {RocketDepositPoolInterface} from "../../interface/deposit/RocketDepositPoolInterface.sol";
99
import {RocketMegapoolFactoryInterface} from "../../interface/megapool/RocketMegapoolFactoryInterface.sol";
1010
import {RocketMegapoolInterface} from "../../interface/megapool/RocketMegapoolInterface.sol";
11-
import {RocketNetworkFeesInterface} from "../../interface/network/RocketNetworkFeesInterface.sol";
12-
import {RocketNetworkVotingInterface} from "../../interface/network/RocketNetworkVotingInterface.sol";
11+
import {RocketMegapoolManagerInterface} from "../../interface/megapool/RocketMegapoolManagerInterface.sol";
1312
import {RocketNetworkSnapshotsInterface} from "../../interface/network/RocketNetworkSnapshotsInterface.sol";
13+
import {RocketNetworkVotingInterface} from "../../interface/network/RocketNetworkVotingInterface.sol";
1414
import {RocketNodeDepositInterface} from "../../interface/node/RocketNodeDepositInterface.sol";
15-
import {RocketNodeManagerInterface} from "../../interface/node/RocketNodeManagerInterface.sol";
1615
import {RocketNodeStakingInterface} from "../../interface/node/RocketNodeStakingInterface.sol";
1716
import {RocketBase} from "../RocketBase.sol";
18-
import {RocketMegapoolManagerInterface} from "../../interface/megapool/RocketMegapoolManagerInterface.sol";
19-
import {RocketVaultWithdrawerInterface} from "../../interface/RocketVaultWithdrawerInterface.sol";
2017

2118
/// @notice Entry point for node operators to perform deposits for the creation of new validators on the network
2219
contract RocketNodeDeposit is RocketBase, RocketNodeDepositInterface, RocketVaultWithdrawerInterface {
@@ -41,15 +38,18 @@ contract RocketNodeDeposit is RocketBase, RocketNodeDepositInterface, RocketVaul
4138

4239
/// @notice Returns the bond requirement for the given number of validators
4340
function getBondRequirement(uint256 _numValidators) override public view returns (uint256) {
41+
if (_numValidators == 0) {
42+
return 0;
43+
}
4444
// Get contracts
4545
RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
4646
// Calculate bond requirement
4747
uint256[] memory baseBondArray = rocketDAOProtocolSettingsNode.getBaseBondArray();
48-
if (_numValidators < baseBondArray.length) {
49-
return baseBondArray[_numValidators];
48+
if (_numValidators - 1 < baseBondArray.length) {
49+
return baseBondArray[_numValidators - 1];
5050
}
5151
uint256 reducedBond = rocketDAOProtocolSettingsNode.getReducedBond();
52-
return baseBondArray[baseBondArray.length - 1] + (1 + _numValidators - baseBondArray.length) * reducedBond;
52+
return baseBondArray[baseBondArray.length - 1] + (_numValidators - baseBondArray.length) * reducedBond;
5353
}
5454

5555
/// @notice Returns a node operator's credit balance in wei
@@ -188,9 +188,6 @@ contract RocketNodeDeposit is RocketBase, RocketNodeDepositInterface, RocketVaul
188188
RocketMegapoolFactoryInterface rocketMegapoolFactory = RocketMegapoolFactoryInterface(getContractAddress("rocketMegapoolFactory"));
189189
RocketMegapoolInterface megapool = RocketMegapoolInterface(rocketMegapoolFactory.getOrDeployContract(msg.sender));
190190
RocketMegapoolManagerInterface rocketMegapoolManager = RocketMegapoolManagerInterface(getContractAddress("rocketMegapoolManager"));
191-
// Check bond requirements
192-
checkBondRequirement(megapool, _bondAmount);
193-
checkDebtRequirement(megapool);
194191
// Request a new validator from the megapool
195192
rocketMegapoolManager.addValidator(address(megapool), megapool.getValidatorCount());
196193
megapool.newValidator(_bondAmount, _useExpressTicket, _validatorPubkey, _validatorSignature, _depositDataRoot);
@@ -229,19 +226,6 @@ contract RocketNodeDeposit is RocketBase, RocketNodeDepositInterface, RocketVaul
229226
rocketNetworkSnapshots.push(key, uint224(ethProvided));
230227
}
231228

232-
/// @dev Checks the bond requirements for a node deposit
233-
function checkBondRequirement(RocketMegapoolInterface _megapool, uint256 _bondAmount) internal {
234-
uint256 totalBondRequired = getBondRequirement(_megapool.getActiveValidatorCount());
235-
uint256 currentBond = _megapool.getNodeBond();
236-
uint256 requiredBond = totalBondRequired - currentBond;
237-
require(_bondAmount == requiredBond, "Bond requirement not met");
238-
}
239-
240-
/// @dev Checks the debt requirements for a node deposit
241-
function checkDebtRequirement(RocketMegapoolInterface _megapool) internal {
242-
require(_megapool.getDebt() == 0, "Cannot create validator while debt exists");
243-
}
244-
245229
/// @dev Initialises node's voting power if not already done
246230
function checkVotingInitialised() private {
247231
// Ensure voting has been initialised for this node

contracts/contract/util/BeaconStateVerifier.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ contract BeaconStateVerifier is RocketBase, BeaconStateVerifierInterface {
5151
// TODO: Extract this out into a parameterised system for updating the gindices alongside hardforks
5252
SSZ.Path memory path = SSZ.from(3, 3); // 0b011 (BeaconBlockHeader -> state_root)
5353
if (isHistorical) {
54-
path = SSZ.concat(path, SSZ.from(11, 5)); // 0b01011 (BeaconState -> validators)
54+
path = SSZ.concat(path, SSZ.from(27, 5)); // 0b01011 (BeaconState -> historical_summaries)
5555
path = SSZ.concat(path, SSZ.intoVector(uint256(_withdrawalSlot) / SLOTS_PER_HISTORICAL_ROOT, 24)); // historical_summaries -> historical_summaries[n]
5656
path = SSZ.concat(path, SSZ.from(0, 1)); // 0b0 (HistoricalSummary -> block_summary_root)
5757
} else {

contracts/interface/deposit/RocketDepositPoolInterface.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface RocketDepositPoolInterface {
1919
function withdrawExcessBalance(uint256 _amount) external;
2020
function requestFunds(uint256 _bondAmount, uint32 _validatorId, uint256 _amount, bool _useExpressTicket) external;
2121
function exitQueue(uint32 _validatorId, bool _expressQueue) external;
22+
function applyCredit(uint256 _amount) external;
2223
function withdrawCredit(uint256 _amount) external;
2324
function getQueueTop() external view returns (address receiver, bool assignmentPossible, uint256 headMovedBlock);
2425
function getQueueIndex() external view returns (uint256);

contracts/interface/megapool/RocketMegapoolDelegateInterface.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-License-Identifier: GPL-3.0-only
1+
// SPDX-License-Identifier: GPL-3.0-onl1000000000y
22
pragma solidity >0.5.0 <0.9.0;
33

44
import "../util/BeaconStateVerifierInterface.sol";
@@ -22,11 +22,13 @@ interface RocketMegapoolDelegateInterface is RocketMegapoolDelegateBaseInterface
2222

2323
function getValidatorCount() external view returns (uint32);
2424
function getActiveValidatorCount() external view returns (uint32);
25+
function getExitingValidatorCount() external view returns (uint32);
26+
function getSoonestWithdrawableEpoch() external view returns (uint32);
2527
function getValidatorInfo(uint32 _validatorId) external view returns (RocketMegapoolStorageLayout.ValidatorInfo memory);
2628
function getAssignedValue() external view returns (uint256);
2729
function getDebt() external view returns (uint256);
2830
function getRefundValue() external view returns (uint256);
29-
function getNodeCapital() external view returns (uint256);
31+
function getNodeRewards() external view returns (uint256);
3032
function getNodeBond() external view returns (uint256);
3133
function getUserCapital() external view returns (uint256);
3234
function calculatePendingRewards() external view returns (uint256 nodeRewards, uint256 voterRewards, uint256 rethRewards);

contracts/interface/util/BeaconStateVerifierInterface.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ struct Withdrawal {
1010

1111
struct ValidatorProof {
1212
uint64 slot;
13-
uint256 validatorIndex;
13+
uint64 validatorIndex;
1414
bytes pubkey;
1515
bytes32 withdrawalCredentials;
1616
bytes32[] witnesses;

test-upgrade/_helpers/upgrade.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,5 +138,7 @@ export async function deployUpgrade(rocketStorageAddress) {
138138
};
139139
}
140140

141+
console.log(addresses);
142+
141143
return upgradeContract;
142144
}

0 commit comments

Comments
 (0)