文件 1 的 35:AddressSetStorageInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface AddressSetStorageInterface {
function getCount(bytes32 _key) external view returns (uint);
function getItem(bytes32 _key, uint _index) external view returns (address);
function getIndexOf(bytes32 _key, address _value) external view returns (int);
function addItem(bytes32 _key, address _value) external;
function removeItem(bytes32 _key, address _value) external;
}
文件 2 的 35:DepositInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface DepositInterface {
function deposit(bytes calldata _pubkey, bytes calldata _withdrawalCredentials, bytes calldata _signature, bytes32 _depositDataRoot) external payable;
}
文件 3 的 35:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 4 的 35:MinipoolDeposit.sol
pragma solidity 0.7.6;
enum MinipoolDeposit {
None,
Full,
Half,
Empty,
Variable
}
文件 5 的 35:MinipoolDetails.sol
pragma solidity 0.7.6;
import "./MinipoolDeposit.sol";
import "./MinipoolStatus.sol";
struct MinipoolDetails {
bool exists;
address minipoolAddress;
bytes pubkey;
MinipoolStatus status;
uint256 statusBlock;
uint256 statusTime;
bool finalised;
MinipoolDeposit depositType;
uint256 nodeFee;
uint256 nodeDepositBalance;
bool nodeDepositAssigned;
uint256 userDepositBalance;
bool userDepositAssigned;
uint256 userDepositAssignedTime;
bool useLatestDelegate;
address delegate;
address previousDelegate;
address effectiveDelegate;
uint256 penaltyCount;
uint256 penaltyRate;
address nodeAddress;
}
文件 6 的 35:MinipoolStatus.sol
pragma solidity 0.7.6;
enum MinipoolStatus {
Initialised,
Prelaunch,
Staking,
Withdrawable,
Dissolved
}
文件 7 的 35:NodeDetails.sol
pragma solidity 0.7.6;
struct NodeDetails {
bool exists;
uint256 registrationTime;
string timezoneLocation;
bool feeDistributorInitialised;
address feeDistributorAddress;
uint256 rewardNetwork;
uint256 rplStake;
uint256 effectiveRPLStake;
uint256 minimumRPLStake;
uint256 maximumRPLStake;
uint256 ethMatched;
uint256 ethMatchedLimit;
uint256 minipoolCount;
uint256 balanceETH;
uint256 balanceRETH;
uint256 balanceRPL;
uint256 balanceOldRPL;
uint256 depositCreditBalance;
uint256 distributorBalanceUserETH;
uint256 distributorBalanceNodeETH;
address withdrawalAddress;
address pendingWithdrawalAddress;
bool smoothingPoolRegistrationState;
uint256 smoothingPoolRegistrationChanged;
address nodeAddress;
}
文件 8 的 35:RocketBase.sol
pragma solidity 0.7.6;
import "../interface/RocketStorageInterface.sol";
abstract contract RocketBase {
uint256 constant calcBase = 1 ether;
uint8 public version;
RocketStorageInterface rocketStorage = RocketStorageInterface(0);
modifier onlyLatestNetworkContract() {
require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract");
_;
}
modifier onlyLatestContract(string memory _contractName, address _contractAddress) {
require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract");
_;
}
modifier onlyRegisteredNode(address _nodeAddress) {
require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node");
_;
}
modifier onlyTrustedNode(address _nodeAddress) {
require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node");
_;
}
modifier onlyRegisteredMinipool(address _minipoolAddress) {
require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool");
_;
}
modifier onlyGuardian() {
require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian");
_;
}
constructor(RocketStorageInterface _rocketStorageAddress) {
rocketStorage = RocketStorageInterface(_rocketStorageAddress);
}
function getContractAddress(string memory _contractName) internal view returns (address) {
address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
require(contractAddress != address(0x0), "Contract not found");
return contractAddress;
}
function getContractAddressUnsafe(string memory _contractName) internal view returns (address) {
address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
return contractAddress;
}
function getContractName(address _contractAddress) internal view returns (string memory) {
string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress)));
require(bytes(contractName).length > 0, "Contract not found");
return contractName;
}
function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
if (_returnData.length < 68) return "Transaction reverted silently";
assembly {
_returnData := add(_returnData, 0x04)
}
return abi.decode(_returnData, (string));
}
function getAddress(bytes32 _key) internal view returns (address) { return rocketStorage.getAddress(_key); }
function getUint(bytes32 _key) internal view returns (uint) { return rocketStorage.getUint(_key); }
function getString(bytes32 _key) internal view returns (string memory) { return rocketStorage.getString(_key); }
function getBytes(bytes32 _key) internal view returns (bytes memory) { return rocketStorage.getBytes(_key); }
function getBool(bytes32 _key) internal view returns (bool) { return rocketStorage.getBool(_key); }
function getInt(bytes32 _key) internal view returns (int) { return rocketStorage.getInt(_key); }
function getBytes32(bytes32 _key) internal view returns (bytes32) { return rocketStorage.getBytes32(_key); }
function setAddress(bytes32 _key, address _value) internal { rocketStorage.setAddress(_key, _value); }
function setUint(bytes32 _key, uint _value) internal { rocketStorage.setUint(_key, _value); }
function setString(bytes32 _key, string memory _value) internal { rocketStorage.setString(_key, _value); }
function setBytes(bytes32 _key, bytes memory _value) internal { rocketStorage.setBytes(_key, _value); }
function setBool(bytes32 _key, bool _value) internal { rocketStorage.setBool(_key, _value); }
function setInt(bytes32 _key, int _value) internal { rocketStorage.setInt(_key, _value); }
function setBytes32(bytes32 _key, bytes32 _value) internal { rocketStorage.setBytes32(_key, _value); }
function deleteAddress(bytes32 _key) internal { rocketStorage.deleteAddress(_key); }
function deleteUint(bytes32 _key) internal { rocketStorage.deleteUint(_key); }
function deleteString(bytes32 _key) internal { rocketStorage.deleteString(_key); }
function deleteBytes(bytes32 _key) internal { rocketStorage.deleteBytes(_key); }
function deleteBool(bytes32 _key) internal { rocketStorage.deleteBool(_key); }
function deleteInt(bytes32 _key) internal { rocketStorage.deleteInt(_key); }
function deleteBytes32(bytes32 _key) internal { rocketStorage.deleteBytes32(_key); }
function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); }
function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); }
}
文件 9 的 35:RocketDAONodeTrustedInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketDAONodeTrustedInterface {
function getBootstrapModeDisabled() external view returns (bool);
function getMemberQuorumVotesRequired() external view returns (uint256);
function getMemberAt(uint256 _index) external view returns (address);
function getMemberCount() external view returns (uint256);
function getMemberMinRequired() external view returns (uint256);
function getMemberIsValid(address _nodeAddress) external view returns (bool);
function getMemberLastProposalTime(address _nodeAddress) external view returns (uint256);
function getMemberID(address _nodeAddress) external view returns (string memory);
function getMemberUrl(address _nodeAddress) external view returns (string memory);
function getMemberJoinedTime(address _nodeAddress) external view returns (uint256);
function getMemberProposalExecutedTime(string memory _proposalType, address _nodeAddress) external view returns (uint256);
function getMemberRPLBondAmount(address _nodeAddress) external view returns (uint256);
function getMemberIsChallenged(address _nodeAddress) external view returns (bool);
function getMemberUnbondedValidatorCount(address _nodeAddress) external view returns (uint256);
function incrementMemberUnbondedValidatorCount(address _nodeAddress) external;
function decrementMemberUnbondedValidatorCount(address _nodeAddress) external;
function bootstrapMember(string memory _id, string memory _url, address _nodeAddress) external;
function bootstrapSettingUint(string memory _settingContractName, string memory _settingPath, uint256 _value) external;
function bootstrapSettingBool(string memory _settingContractName, string memory _settingPath, bool _value) external;
function bootstrapUpgrade(string memory _type, string memory _name, string memory _contractAbi, address _contractAddress) external;
function bootstrapDisable(bool _confirmDisableBootstrapMode) external;
function memberJoinRequired(string memory _id, string memory _url) external;
}
文件 10 的 35:RocketDAONodeTrustedSettingsMinipoolInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketDAONodeTrustedSettingsMinipoolInterface {
function getScrubPeriod() external view returns(uint256);
function getPromotionScrubPeriod() external view returns(uint256);
function getScrubQuorum() external view returns(uint256);
function getCancelBondReductionQuorum() external view returns(uint256);
function getScrubPenaltyEnabled() external view returns(bool);
function isWithinBondReductionWindow(uint256 _time) external view returns (bool);
function getBondReductionWindowStart() external view returns (uint256);
function getBondReductionWindowLength() external view returns (uint256);
}
文件 11 的 35:RocketDAOProtocolSettingsMinipoolInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "../../../../types/MinipoolDeposit.sol";
interface RocketDAOProtocolSettingsMinipoolInterface {
function getLaunchBalance() external view returns (uint256);
function getPreLaunchValue() external pure returns (uint256);
function getDepositUserAmount(MinipoolDeposit _depositType) external view returns (uint256);
function getFullDepositUserAmount() external view returns (uint256);
function getHalfDepositUserAmount() external view returns (uint256);
function getVariableDepositAmount() external view returns (uint256);
function getSubmitWithdrawableEnabled() external view returns (bool);
function getBondReductionEnabled() external view returns (bool);
function getLaunchTimeout() external view returns (uint256);
function getMaximumCount() external view returns (uint256);
function isWithinUserDistributeWindow(uint256 _time) external view returns (bool);
function hasUserDistributeWindowPassed(uint256 _time) external view returns (bool);
function getUserDistributeWindowStart() external view returns (uint256);
function getUserDistributeWindowLength() external view returns (uint256);
}
文件 12 的 35:RocketDAOProtocolSettingsNodeInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketDAOProtocolSettingsNodeInterface {
function getRegistrationEnabled() external view returns (bool);
function getSmoothingPoolRegistrationEnabled() external view returns (bool);
function getDepositEnabled() external view returns (bool);
function getVacantMinipoolsEnabled() external view returns (bool);
function getMinimumPerMinipoolStake() external view returns (uint256);
function getMaximumPerMinipoolStake() external view returns (uint256);
}
文件 13 的 35:RocketDepositPoolInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketDepositPoolInterface {
function getBalance() external view returns (uint256);
function getNodeBalance() external view returns (uint256);
function getUserBalance() external view returns (int256);
function getExcessBalance() external view returns (uint256);
function deposit() external payable;
function getMaximumDepositAmount() external view returns (uint256);
function nodeDeposit(uint256 _totalAmount) external payable;
function nodeCreditWithdrawal(uint256 _amount) external;
function recycleDissolvedDeposit() external payable;
function recycleExcessCollateral() external payable;
function recycleLiquidatedStake() external payable;
function assignDeposits() external;
function maybeAssignDeposits() external returns (bool);
function withdrawExcessBalance(uint256 _amount) external;
}
文件 14 的 35:RocketMinipoolBase.sol
pragma solidity 0.7.6;
import "./RocketMinipoolStorageLayout.sol";
import "../../interface/RocketStorageInterface.sol";
import "../../interface/minipool/RocketMinipoolBaseInterface.sol";
contract RocketMinipoolBase is RocketMinipoolBaseInterface, RocketMinipoolStorageLayout {
event EtherReceived(address indexed from, uint256 amount, uint256 time);
event DelegateUpgraded(address oldDelegate, address newDelegate, uint256 time);
event DelegateRolledBack(address oldDelegate, address newDelegate, uint256 time);
address immutable self;
constructor () {
self = address(this);
}
modifier notSelf() {
require(address(this) != self);
_;
}
modifier onlyMinipoolOwner() {
address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(nodeAddress);
require(msg.sender == nodeAddress || msg.sender == withdrawalAddress, "Only the node operator can access this method");
_;
}
function initialise(address _rocketStorage, address _nodeAddress) external override notSelf {
require(_nodeAddress != address(0), "Invalid node address");
require(storageState == StorageState.Undefined, "Already initialised");
storageState = StorageState.Uninitialised;
rocketStorage = RocketStorageInterface(_rocketStorage);
address delegateAddress = getContractAddress("rocketMinipoolDelegate");
rocketMinipoolDelegate = delegateAddress;
require(contractExists(delegateAddress), "Delegate contract does not exist");
(bool success, bytes memory data) = delegateAddress.delegatecall(abi.encodeWithSignature('initialise(address)', _nodeAddress));
if (!success) { revert(getRevertMessage(data)); }
}
receive() external payable notSelf {
emit EtherReceived(msg.sender, msg.value, block.timestamp);
}
function delegateUpgrade() external override onlyMinipoolOwner notSelf {
rocketMinipoolDelegatePrev = rocketMinipoolDelegate;
rocketMinipoolDelegate = getContractAddress("rocketMinipoolDelegate");
require(rocketMinipoolDelegate != rocketMinipoolDelegatePrev, "New delegate is the same as the existing one");
emit DelegateUpgraded(rocketMinipoolDelegatePrev, rocketMinipoolDelegate, block.timestamp);
}
function delegateRollback() external override onlyMinipoolOwner notSelf {
require(rocketMinipoolDelegatePrev != address(0x0), "Previous delegate contract is not set");
address originalDelegate = rocketMinipoolDelegate;
rocketMinipoolDelegate = rocketMinipoolDelegatePrev;
rocketMinipoolDelegatePrev = address(0x0);
emit DelegateRolledBack(originalDelegate, rocketMinipoolDelegate, block.timestamp);
}
function setUseLatestDelegate(bool _setting) external override onlyMinipoolOwner notSelf {
useLatestDelegate = _setting;
}
function getUseLatestDelegate() external override view returns (bool) {
return useLatestDelegate;
}
function getDelegate() external override view returns (address) {
return rocketMinipoolDelegate;
}
function getPreviousDelegate() external override view returns (address) {
return rocketMinipoolDelegatePrev;
}
function getEffectiveDelegate() external override view returns (address) {
return useLatestDelegate ? getContractAddress("rocketMinipoolDelegate") : rocketMinipoolDelegate;
}
fallback(bytes calldata _input) external payable notSelf returns (bytes memory) {
address delegateContract = useLatestDelegate ? getContractAddress("rocketMinipoolDelegate") : rocketMinipoolDelegate;
require(contractExists(delegateContract), "Delegate contract does not exist");
(bool success, bytes memory data) = delegateContract.delegatecall(_input);
if (!success) { revert(getRevertMessage(data)); }
return data;
}
function getContractAddress(string memory _contractName) private view returns (address) {
address contractAddress = rocketStorage.getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
require(contractAddress != address(0x0), "Contract not found");
return contractAddress;
}
function getRevertMessage(bytes memory _returnData) private pure returns (string memory) {
if (_returnData.length < 68) { return "Transaction reverted silently"; }
assembly {
_returnData := add(_returnData, 0x04)
}
return abi.decode(_returnData, (string));
}
function contractExists(address _contractAddress) private view returns (bool) {
uint32 codeSize;
assembly {
codeSize := extcodesize(_contractAddress)
}
return codeSize > 0;
}
}
文件 15 的 35:RocketMinipoolBaseInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketMinipoolBaseInterface {
function initialise(address _rocketStorage, address _nodeAddress) external;
function delegateUpgrade() external;
function delegateRollback() external;
function setUseLatestDelegate(bool _setting) external;
function getUseLatestDelegate() external view returns (bool);
function getDelegate() external view returns (address);
function getPreviousDelegate() external view returns (address);
function getEffectiveDelegate() external view returns (address);
}
文件 16 的 35:RocketMinipoolBondReducerInterface.sol
pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;
interface RocketMinipoolBondReducerInterface {
function beginReduceBondAmount(address _minipoolAddress, uint256 _newBondAmount) external;
function getReduceBondTime(address _minipoolAddress) external view returns (uint256);
function getReduceBondValue(address _minipoolAddress) external view returns (uint256);
function getReduceBondCancelled(address _minipoolAddress) external view returns (bool);
function canReduceBondAmount(address _minipoolAddress) external view returns (bool);
function voteCancelReduction(address _minipoolAddress) external;
function reduceBondAmount() external returns (uint256);
function getLastBondReductionTime(address _minipoolAddress) external view returns (uint256);
function getLastBondReductionPrevValue(address _minipoolAddress) external view returns (uint256);
function getLastBondReductionPrevNodeFee(address _minipoolAddress) external view returns (uint256);
}
文件 17 的 35:RocketMinipoolDelegate.sol
pragma solidity 0.7.6;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "./RocketMinipoolStorageLayout.sol";
import "../../interface/casper/DepositInterface.sol";
import "../../interface/deposit/RocketDepositPoolInterface.sol";
import "../../interface/minipool/RocketMinipoolInterface.sol";
import "../../interface/minipool/RocketMinipoolManagerInterface.sol";
import "../../interface/minipool/RocketMinipoolQueueInterface.sol";
import "../../interface/minipool/RocketMinipoolPenaltyInterface.sol";
import "../../interface/node/RocketNodeStakingInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsMinipoolInterface.sol";
import "../../interface/dao/node/settings/RocketDAONodeTrustedSettingsMinipoolInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol";
import "../../interface/dao/node/RocketDAONodeTrustedInterface.sol";
import "../../interface/network/RocketNetworkFeesInterface.sol";
import "../../interface/token/RocketTokenRETHInterface.sol";
import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolStatus.sol";
import "../../interface/node/RocketNodeDepositInterface.sol";
import "../../interface/minipool/RocketMinipoolBondReducerInterface.sol";
contract RocketMinipoolDelegate is RocketMinipoolStorageLayout, RocketMinipoolInterface {
uint8 public constant override version = 3;
uint256 constant calcBase = 1 ether;
uint256 constant legacyPrelaunchAmount = 16 ether;
using SafeMath for uint;
event StatusUpdated(uint8 indexed status, uint256 time);
event ScrubVoted(address indexed member, uint256 time);
event BondReduced(uint256 previousBondAmount, uint256 newBondAmount, uint256 time);
event MinipoolScrubbed(uint256 time);
event MinipoolPrestaked(bytes validatorPubkey, bytes validatorSignature, bytes32 depositDataRoot, uint256 amount, bytes withdrawalCredentials, uint256 time);
event MinipoolPromoted(uint256 time);
event MinipoolVacancyPrepared(uint256 bondAmount, uint256 currentBalance, uint256 time);
event EtherDeposited(address indexed from, uint256 amount, uint256 time);
event EtherWithdrawn(address indexed to, uint256 amount, uint256 time);
event EtherWithdrawalProcessed(address indexed executed, uint256 nodeAmount, uint256 userAmount, uint256 totalBalance, uint256 time);
function getStatus() override external view returns (MinipoolStatus) { return status; }
function getFinalised() override external view returns (bool) { return finalised; }
function getStatusBlock() override external view returns (uint256) { return statusBlock; }
function getStatusTime() override external view returns (uint256) { return statusTime; }
function getScrubVoted(address _member) override external view returns (bool) { return memberScrubVotes[_member]; }
function getDepositType() override external view returns (MinipoolDeposit) { return depositType; }
function getNodeAddress() override external view returns (address) { return nodeAddress; }
function getNodeFee() override external view returns (uint256) { return nodeFee; }
function getNodeDepositBalance() override external view returns (uint256) { return nodeDepositBalance; }
function getNodeRefundBalance() override external view returns (uint256) { return nodeRefundBalance; }
function getNodeDepositAssigned() override external view returns (bool) { return userDepositAssignedTime != 0; }
function getPreLaunchValue() override external view returns (uint256) { return preLaunchValue; }
function getNodeTopUpValue() override external view returns (uint256) { return nodeDepositBalance.sub(preLaunchValue); }
function getVacant() override external view returns (bool) { return vacant; }
function getPreMigrationBalance() override external view returns (uint256) { return preMigrationBalance; }
function getUserDistributed() override external view returns (bool) { return userDistributed; }
function getUserDepositBalance() override public view returns (uint256) {
if (depositType == MinipoolDeposit.Variable) {
return userDepositBalance;
} else {
return userDepositBalanceLegacy;
}
}
function getUserDepositAssigned() override external view returns (bool) { return userDepositAssignedTime != 0; }
function getUserDepositAssignedTime() override external view returns (uint256) { return userDepositAssignedTime; }
function getTotalScrubVotes() override external view returns (uint256) { return totalScrubVotes; }
modifier onlyInitialised() {
require(storageState == StorageState.Initialised, "Storage state not initialised");
_;
}
modifier onlyUninitialised() {
require(storageState == StorageState.Uninitialised, "Storage state already initialised");
_;
}
modifier onlyMinipoolOwner(address _nodeAddress) {
require(_nodeAddress == nodeAddress, "Invalid minipool owner");
_;
}
modifier onlyMinipoolOwnerOrWithdrawalAddress(address _nodeAddress) {
require(_nodeAddress == nodeAddress || _nodeAddress == rocketStorage.getNodeWithdrawalAddress(nodeAddress), "Invalid minipool owner");
_;
}
modifier onlyLatestContract(string memory _contractName, address _contractAddress) {
require(_contractAddress == getContractAddress(_contractName), "Invalid or outdated contract");
_;
}
function getContractAddress(string memory _contractName) private view returns (address) {
address contractAddress = rocketStorage.getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
require(contractAddress != address(0x0), "Contract not found");
return contractAddress;
}
function initialise(address _nodeAddress) override external onlyUninitialised {
require(_nodeAddress != address(0x0), "Invalid node address");
RocketNetworkFeesInterface rocketNetworkFees = RocketNetworkFeesInterface(getContractAddress("rocketNetworkFees"));
status = MinipoolStatus.Initialised;
statusBlock = block.number;
statusTime = block.timestamp;
depositType = MinipoolDeposit.Variable;
nodeAddress = _nodeAddress;
nodeFee = rocketNetworkFees.getNodeFee();
rocketTokenRETH = getContractAddress("rocketTokenRETH");
rocketMinipoolPenalty = getContractAddress("rocketMinipoolPenalty");
storageState = StorageState.Initialised;
}
function preDeposit(uint256 _bondValue, bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot) override external payable onlyLatestContract("rocketNodeDeposit", msg.sender) onlyInitialised {
require(status == MinipoolStatus.Initialised, "The pre-deposit can only be made while initialised");
require(preLaunchValue == 0, "Pre-deposit already performed");
nodeDepositBalance = _bondValue;
preLaunchValue = msg.value;
emit EtherDeposited(msg.sender, preLaunchValue, block.timestamp);
preStake(_validatorPubkey, _validatorSignature, _depositDataRoot);
}
function deposit() override external payable onlyLatestContract("rocketDepositPool", msg.sender) onlyInitialised {
require(status == MinipoolStatus.Initialised, "The node deposit can only be assigned while initialised");
require(userDepositAssignedTime == 0, "The user deposit has already been assigned");
setStatus(MinipoolStatus.Prelaunch);
userDepositBalance = msg.value.add(preLaunchValue).sub(nodeDepositBalance);
userDepositAssignedTime = block.timestamp;
emit EtherDeposited(msg.sender, msg.value, block.timestamp);
}
function userDeposit() override external payable onlyLatestContract("rocketDepositPool", msg.sender) onlyInitialised {
require(status >= MinipoolStatus.Initialised && status <= MinipoolStatus.Staking, "The user deposit can only be assigned while initialised, in prelaunch, or staking");
require(userDepositAssignedTime == 0, "The user deposit has already been assigned");
if (status == MinipoolStatus.Initialised) { setStatus(MinipoolStatus.Prelaunch); }
userDepositBalance = msg.value;
userDepositAssignedTime = block.timestamp;
if (depositType == MinipoolDeposit.Full) {
nodeDepositBalance = nodeDepositBalance.sub(msg.value);
nodeRefundBalance = nodeRefundBalance.add(msg.value);
}
emit EtherDeposited(msg.sender, msg.value, block.timestamp);
}
function refund() override external onlyMinipoolOwnerOrWithdrawalAddress(msg.sender) onlyInitialised {
require(nodeRefundBalance > 0, "No amount of the node deposit is available for refund");
if (!finalised && userDistributed) {
_finalise();
} else {
_refund();
}
}
function slash() external override onlyInitialised {
require(nodeSlashBalance > 0, "No balance to slash");
_slash();
}
function canStake() override external view onlyInitialised returns (bool) {
if (status != MinipoolStatus.Prelaunch) {
return false;
}
RocketDAONodeTrustedSettingsMinipoolInterface rocketDAONodeTrustedSettingsMinipool = RocketDAONodeTrustedSettingsMinipoolInterface(getContractAddress("rocketDAONodeTrustedSettingsMinipool"));
uint256 scrubPeriod = rocketDAONodeTrustedSettingsMinipool.getScrubPeriod();
return block.timestamp > statusTime + scrubPeriod;
}
function canPromote() override external view onlyInitialised returns (bool) {
if (status != MinipoolStatus.Prelaunch) {
return false;
}
RocketDAONodeTrustedSettingsMinipoolInterface rocketDAONodeTrustedSettingsMinipool = RocketDAONodeTrustedSettingsMinipoolInterface(getContractAddress("rocketDAONodeTrustedSettingsMinipool"));
uint256 scrubPeriod = rocketDAONodeTrustedSettingsMinipool.getPromotionScrubPeriod();
return block.timestamp > statusTime + scrubPeriod;
}
function stake(bytes calldata _validatorSignature, bytes32 _depositDataRoot) override external onlyMinipoolOwner(msg.sender) onlyInitialised {
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
{
RocketDAONodeTrustedSettingsMinipoolInterface rocketDAONodeTrustedSettingsMinipool = RocketDAONodeTrustedSettingsMinipoolInterface(getContractAddress("rocketDAONodeTrustedSettingsMinipool"));
uint256 scrubPeriod = rocketDAONodeTrustedSettingsMinipool.getScrubPeriod();
require(status == MinipoolStatus.Prelaunch, "The minipool can only begin staking while in prelaunch");
require(block.timestamp > statusTime + scrubPeriod, "Not enough time has passed to stake");
require(!vacant, "Cannot stake a vacant minipool");
}
setStatus(MinipoolStatus.Staking);
DepositInterface casperDeposit = DepositInterface(getContractAddress("casperDeposit"));
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
uint256 launchAmount = rocketDAOProtocolSettingsMinipool.getLaunchBalance();
uint256 depositAmount;
if (depositType == MinipoolDeposit.Variable) {
depositAmount = launchAmount.sub(preLaunchValue);
} else {
depositAmount = launchAmount.sub(legacyPrelaunchAmount);
}
require(address(this).balance >= depositAmount, "Insufficient balance to begin staking");
bytes memory validatorPubkey = rocketMinipoolManager.getMinipoolPubkey(address(this));
casperDeposit.deposit{value : depositAmount}(validatorPubkey, rocketMinipoolManager.getMinipoolWithdrawalCredentials(address(this)), _validatorSignature, _depositDataRoot);
rocketMinipoolManager.incrementNodeStakingMinipoolCount(nodeAddress);
}
function prepareVacancy(uint256 _bondAmount, uint256 _currentBalance) override external onlyLatestContract("rocketMinipoolManager", msg.sender) onlyInitialised {
require(status == MinipoolStatus.Initialised, "Must be in initialised status");
require(nodeRefundBalance == 0, "Refund balance not zero");
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
uint256 launchAmount = rocketDAOProtocolSettingsMinipool.getLaunchBalance();
require(_currentBalance >= launchAmount, "Balance is too low");
nodeDepositBalance = _bondAmount;
userDepositBalance = launchAmount.sub(nodeDepositBalance);
vacant = true;
preMigrationBalance = _currentBalance;
nodeRefundBalance = _currentBalance.sub(launchAmount);
setStatus(MinipoolStatus.Prelaunch);
emit MinipoolVacancyPrepared(_bondAmount, _currentBalance, block.timestamp);
}
function promote() override external onlyMinipoolOwner(msg.sender) onlyInitialised {
require(status == MinipoolStatus.Prelaunch, "The minipool can only promote while in prelaunch");
require(vacant, "Cannot promote a non-vacant minipool");
RocketDAONodeTrustedSettingsMinipoolInterface rocketDAONodeTrustedSettingsMinipool = RocketDAONodeTrustedSettingsMinipoolInterface(getContractAddress("rocketDAONodeTrustedSettingsMinipool"));
vacant = false;
uint256 scrubPeriod = rocketDAONodeTrustedSettingsMinipool.getPromotionScrubPeriod();
require(block.timestamp > statusTime + scrubPeriod, "Not enough time has passed to promote");
setStatus(MinipoolStatus.Staking);
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
rocketMinipoolManager.incrementNodeStakingMinipoolCount(nodeAddress);
userDepositAssignedTime = block.timestamp;
RocketNodeDepositInterface rocketNodeDepositInterface = RocketNodeDepositInterface(getContractAddress("rocketNodeDeposit"));
rocketNodeDepositInterface.increaseDepositCreditBalance(nodeAddress, userDepositBalance);
rocketMinipoolManager.removeVacantMinipool();
emit MinipoolPromoted(block.timestamp);
}
function preStake(bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot) internal {
DepositInterface casperDeposit = DepositInterface(getContractAddress("casperDeposit"));
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
rocketMinipoolManager.setMinipoolPubkey(_validatorPubkey);
bytes memory withdrawalCredentials = rocketMinipoolManager.getMinipoolWithdrawalCredentials(address(this));
casperDeposit.deposit{value : preLaunchValue}(_validatorPubkey, withdrawalCredentials, _validatorSignature, _depositDataRoot);
emit MinipoolPrestaked(_validatorPubkey, _validatorSignature, _depositDataRoot, preLaunchValue, withdrawalCredentials, block.timestamp);
}
function distributeBalance(bool _rewardsOnly) override external onlyInitialised {
address nodeWithdrawalAddress = rocketStorage.getNodeWithdrawalAddress(nodeAddress);
bool ownerCalling = msg.sender == nodeAddress || msg.sender == nodeWithdrawalAddress;
if (status == MinipoolStatus.Dissolved) {
require(ownerCalling, "Only owner can distribute dissolved minipool");
distributeToOwner();
return;
}
require(status == MinipoolStatus.Staking, "Minipool must be staking");
uint256 totalBalance = address(this).balance.sub(nodeRefundBalance);
if (totalBalance >= 8 ether) {
require(!_rewardsOnly, "Balance exceeds 8 ether");
_distributeBalance(totalBalance);
if (ownerCalling) {
_finalise();
} else {
require(userDistributeAllowed(), "Only owner can distribute right now");
userDistributed = true;
}
} else {
distributeSkimmedRewards();
if (ownerCalling && nodeRefundBalance > 0) {
_refund();
}
}
userDistributeTime = 0;
}
function distributeToOwner() internal {
uint256 balance = address(this).balance;
address nodeWithdrawalAddress = rocketStorage.getNodeWithdrawalAddress(nodeAddress);
(bool success,) = nodeWithdrawalAddress.call{value : balance}("");
require(success, "Node ETH balance was not successfully transferred to node operator");
emit EtherWithdrawn(nodeWithdrawalAddress, balance, block.timestamp);
}
function beginUserDistribute() override external onlyInitialised {
require(status == MinipoolStatus.Staking, "Minipool must be staking");
uint256 totalBalance = address(this).balance.sub(nodeRefundBalance);
require (totalBalance >= 8 ether, "Balance too low");
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
uint256 timeElapsed = block.timestamp.sub(userDistributeTime);
require(rocketDAOProtocolSettingsMinipool.hasUserDistributeWindowPassed(timeElapsed), "User distribution already pending");
userDistributeTime = block.timestamp;
}
function userDistributeAllowed() override public view returns (bool) {
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
uint256 timeElapsed = block.timestamp.sub(userDistributeTime);
return(rocketDAOProtocolSettingsMinipool.isWithinUserDistributeWindow(timeElapsed));
}
function finalise() override external onlyMinipoolOwnerOrWithdrawalAddress(msg.sender) onlyInitialised {
require(userDistributed, "Can only manually finalise after user distribution");
_finalise();
}
function _finalise() private {
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
require(!finalised, "Minipool has already been finalised");
finalised = true;
if (nodeSlashBalance > 0) {
_slash();
}
if (nodeRefundBalance > 0) {
_refund();
}
if (address(this).balance > 0) {
payable(rocketTokenRETH).transfer(address(this).balance);
}
RocketTokenRETHInterface(rocketTokenRETH).depositExcessCollateral();
rocketMinipoolManager.incrementNodeFinalisedMinipoolCount(nodeAddress);
rocketMinipoolManager.decrementNodeStakingMinipoolCount(nodeAddress);
}
function _distributeBalance(uint256 _balance) private {
uint256 nodeAmount = 0;
uint256 userCapital = getUserDepositBalance();
if (_balance < userCapital) {
if (withdrawalBlock == 0) {
nodeSlashBalance = userCapital.sub(_balance);
}
} else {
nodeAmount = _calculateNodeShare(_balance);
}
uint256 userAmount = _balance.sub(nodeAmount);
nodeRefundBalance = nodeRefundBalance.add(nodeAmount);
if (userAmount > 0) {
payable(rocketTokenRETH).transfer(userAmount);
}
withdrawalBlock = block.number;
emit EtherWithdrawalProcessed(msg.sender, nodeAmount, userAmount, _balance, block.timestamp);
}
function calculateNodeShare(uint256 _balance) override public view returns (uint256) {
if (_balance < 8 ether) {
return calculateNodeRewards(nodeDepositBalance, getUserDepositBalance(), _balance);
} else {
return _calculateNodeShare(_balance);
}
}
function calculateUserShare(uint256 _balance) override external view returns (uint256) {
return _balance.sub(calculateNodeShare(_balance));
}
function _calculateNodeShare(uint256 _balance) internal view returns (uint256) {
uint256 userCapital = getUserDepositBalance();
uint256 nodeCapital = nodeDepositBalance;
uint256 nodeShare = 0;
uint256 capital = userCapital.add(nodeCapital);
if (_balance > capital) {
uint256 rewards = _balance.sub(capital);
nodeShare = nodeCapital.add(calculateNodeRewards(nodeCapital, userCapital, rewards));
} else if (_balance > userCapital) {
nodeShare = _balance.sub(userCapital);
}
uint256 penaltyRate = RocketMinipoolPenaltyInterface(rocketMinipoolPenalty).getPenaltyRate(address(this));
if (penaltyRate > 0) {
uint256 penaltyAmount = nodeShare.mul(penaltyRate).div(calcBase);
if (penaltyAmount > nodeShare) {
penaltyAmount = nodeShare;
}
nodeShare = nodeShare.sub(penaltyAmount);
}
return nodeShare;
}
function calculateNodeRewards(uint256 _nodeCapital, uint256 _userCapital, uint256 _rewards) internal view returns (uint256) {
uint256 nodePortion = _rewards.mul(_nodeCapital).div(_userCapital.add(_nodeCapital));
uint256 userPortion = _rewards.sub(nodePortion);
return nodePortion.add(userPortion.mul(nodeFee).div(calcBase));
}
function dissolve() override external onlyInitialised {
require(status == MinipoolStatus.Prelaunch, "The minipool can only be dissolved while in prelaunch");
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
require(block.timestamp.sub(statusTime) >= rocketDAOProtocolSettingsMinipool.getLaunchTimeout(), "The minipool can only be dissolved once it has timed out");
_dissolve();
}
function close() override external onlyMinipoolOwner(msg.sender) onlyInitialised {
require(status == MinipoolStatus.Dissolved, "The minipool can only be closed while dissolved");
distributeToOwner();
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
require(rocketMinipoolManager.getMinipoolExists(address(this)), "Minipool already closed");
rocketMinipoolManager.destroyMinipool();
nodeDepositBalance = 0;
nodeRefundBalance = 0;
userDepositBalance = 0;
userDepositBalanceLegacy = 0;
userDepositAssignedTime = 0;
}
function voteScrub() override external onlyInitialised {
require(status == MinipoolStatus.Prelaunch, "The minipool can only be scrubbed while in prelaunch");
RocketDAONodeTrustedInterface rocketDAONode = RocketDAONodeTrustedInterface(getContractAddress("rocketDAONodeTrusted"));
RocketDAONodeTrustedSettingsMinipoolInterface rocketDAONodeTrustedSettingsMinipool = RocketDAONodeTrustedSettingsMinipoolInterface(getContractAddress("rocketDAONodeTrustedSettingsMinipool"));
require(rocketDAONode.getMemberIsValid(msg.sender), "Not a trusted member");
require(!memberScrubVotes[msg.sender], "Member has already voted to scrub");
memberScrubVotes[msg.sender] = true;
emit ScrubVoted(msg.sender, block.timestamp);
uint256 quorum = rocketDAONode.getMemberCount().mul(rocketDAONodeTrustedSettingsMinipool.getScrubQuorum()).div(calcBase);
if (totalScrubVotes.add(1) > quorum) {
if (!vacant && rocketDAONodeTrustedSettingsMinipool.getScrubPenaltyEnabled()){
RocketNodeStakingInterface rocketNodeStaking = RocketNodeStakingInterface(getContractAddress("rocketNodeStaking"));
RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
uint256 launchAmount = rocketDAOProtocolSettingsMinipool.getLaunchBalance();
rocketNodeStaking.slashRPL(
nodeAddress,
launchAmount.sub(nodeDepositBalance)
.mul(rocketDAOProtocolSettingsNode.getMinimumPerMinipoolStake())
.div(calcBase)
);
}
_dissolve();
emit MinipoolScrubbed(block.timestamp);
} else {
totalScrubVotes = totalScrubVotes.add(1);
}
}
function reduceBondAmount() override external onlyMinipoolOwner(msg.sender) onlyInitialised {
require(status == MinipoolStatus.Staking, "Minipool must be staking");
uint256 totalBalance = address(this).balance.sub(nodeRefundBalance);
require(totalBalance < 8 ether, "Cannot reduce bond with balance of 8 ether or more");
distributeSkimmedRewards();
RocketMinipoolBondReducerInterface rocketBondReducer = RocketMinipoolBondReducerInterface(getContractAddress("rocketMinipoolBondReducer"));
uint256 previousBond = nodeDepositBalance;
uint256 newBond = rocketBondReducer.reduceBondAmount();
userDepositBalance = getUserDepositBalance().add(previousBond.sub(newBond));
nodeDepositBalance = newBond;
RocketNetworkFeesInterface rocketNetworkFees = RocketNetworkFeesInterface(getContractAddress("rocketNetworkFees"));
uint256 prevFee = nodeFee;
uint256 newFee = rocketNetworkFees.getNodeFee();
nodeFee = newFee;
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
rocketMinipoolManager.updateNodeStakingMinipoolCount(previousBond, newBond, prevFee, newFee);
if (depositType != MinipoolDeposit.Variable) {
userDepositBalanceLegacy = 2 ** 256 - 1;
depositType = MinipoolDeposit.Variable;
}
emit BondReduced(previousBond, newBond, block.timestamp);
}
function distributeSkimmedRewards() internal {
uint256 rewards = address(this).balance.sub(nodeRefundBalance);
uint256 nodeShare = calculateNodeRewards(nodeDepositBalance, getUserDepositBalance(), rewards);
nodeRefundBalance = nodeRefundBalance.add(nodeShare);
payable(rocketTokenRETH).transfer(rewards.sub(nodeShare));
}
function setStatus(MinipoolStatus _status) private {
status = _status;
statusBlock = block.number;
statusTime = block.timestamp;
emit StatusUpdated(uint8(_status), block.timestamp);
}
function _refund() private {
require(vacant == false, "Vacant minipool cannot refund");
uint256 refundAmount = nodeRefundBalance;
nodeRefundBalance = 0;
address nodeWithdrawalAddress = rocketStorage.getNodeWithdrawalAddress(nodeAddress);
(bool success,) = nodeWithdrawalAddress.call{value : refundAmount}("");
require(success, "ETH refund amount was not successfully transferred to node operator");
emit EtherWithdrawn(nodeWithdrawalAddress, refundAmount, block.timestamp);
}
function _slash() private {
RocketNodeStakingInterface rocketNodeStaking = RocketNodeStakingInterface(getContractAddress("rocketNodeStaking"));
uint256 slashAmount = nodeSlashBalance;
nodeSlashBalance = 0;
rocketNodeStaking.slashRPL(nodeAddress, slashAmount);
}
function _dissolve() private {
RocketDepositPoolInterface rocketDepositPool = RocketDepositPoolInterface(getContractAddress("rocketDepositPool"));
RocketMinipoolQueueInterface rocketMinipoolQueue = RocketMinipoolQueueInterface(getContractAddress("rocketMinipoolQueue"));
setStatus(MinipoolStatus.Dissolved);
if (vacant) {
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
rocketMinipoolManager.removeVacantMinipool();
} else {
if (depositType == MinipoolDeposit.Full) {
rocketMinipoolQueue.removeMinipool(MinipoolDeposit.Full);
} else {
uint256 userCapital = getUserDepositBalance();
rocketDepositPool.recycleDissolvedDeposit{value : userCapital}();
emit EtherWithdrawn(address(rocketDepositPool), userCapital, block.timestamp);
}
}
}
}
文件 18 的 35:RocketMinipoolFactoryInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "../../types/MinipoolDeposit.sol";
interface RocketMinipoolFactoryInterface {
function getExpectedAddress(address _nodeAddress, uint256 _salt) external view returns (address);
function deployContract(address _nodeAddress, uint256 _salt) external returns (address);
}
文件 19 的 35:RocketMinipoolInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolStatus.sol";
import "../RocketStorageInterface.sol";
interface RocketMinipoolInterface {
function version() external view returns (uint8);
function initialise(address _nodeAddress) external;
function getStatus() external view returns (MinipoolStatus);
function getFinalised() external view returns (bool);
function getStatusBlock() external view returns (uint256);
function getStatusTime() external view returns (uint256);
function getScrubVoted(address _member) external view returns (bool);
function getDepositType() external view returns (MinipoolDeposit);
function getNodeAddress() external view returns (address);
function getNodeFee() external view returns (uint256);
function getNodeDepositBalance() external view returns (uint256);
function getNodeRefundBalance() external view returns (uint256);
function getNodeDepositAssigned() external view returns (bool);
function getPreLaunchValue() external view returns (uint256);
function getNodeTopUpValue() external view returns (uint256);
function getVacant() external view returns (bool);
function getPreMigrationBalance() external view returns (uint256);
function getUserDistributed() external view returns (bool);
function getUserDepositBalance() external view returns (uint256);
function getUserDepositAssigned() external view returns (bool);
function getUserDepositAssignedTime() external view returns (uint256);
function getTotalScrubVotes() external view returns (uint256);
function calculateNodeShare(uint256 _balance) external view returns (uint256);
function calculateUserShare(uint256 _balance) external view returns (uint256);
function preDeposit(uint256 _bondingValue, bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot) external payable;
function deposit() external payable;
function userDeposit() external payable;
function distributeBalance(bool _rewardsOnly) external;
function beginUserDistribute() external;
function userDistributeAllowed() external view returns (bool);
function refund() external;
function slash() external;
function finalise() external;
function canStake() external view returns (bool);
function canPromote() external view returns (bool);
function stake(bytes calldata _validatorSignature, bytes32 _depositDataRoot) external;
function prepareVacancy(uint256 _bondAmount, uint256 _currentBalance) external;
function promote() external;
function dissolve() external;
function close() external;
function voteScrub() external;
function reduceBondAmount() external;
}
文件 20 的 35:RocketMinipoolManager.sol
pragma solidity 0.7.6;
pragma abicoder v2;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../RocketBase.sol";
import "./RocketMinipoolBase.sol";
import "../../types/MinipoolStatus.sol";
import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolDetails.sol";
import "../../interface/dao/node/RocketDAONodeTrustedInterface.sol";
import "../../interface/minipool/RocketMinipoolInterface.sol";
import "../../interface/minipool/RocketMinipoolManagerInterface.sol";
import "../../interface/node/RocketNodeStakingInterface.sol";
import "../../interface/util/AddressSetStorageInterface.sol";
import "../../interface/node/RocketNodeManagerInterface.sol";
import "../../interface/network/RocketNetworkPricesInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsMinipoolInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol";
import "../../interface/minipool/RocketMinipoolFactoryInterface.sol";
import "../../interface/node/RocketNodeDistributorFactoryInterface.sol";
import "../../interface/node/RocketNodeDistributorInterface.sol";
import "../../interface/network/RocketNetworkPenaltiesInterface.sol";
import "../../interface/minipool/RocketMinipoolPenaltyInterface.sol";
import "../../interface/node/RocketNodeDepositInterface.sol";
import "./RocketMinipoolDelegate.sol";
contract RocketMinipoolManager is RocketBase, RocketMinipoolManagerInterface {
using SafeMath for uint;
event MinipoolCreated(address indexed minipool, address indexed node, uint256 time);
event MinipoolDestroyed(address indexed minipool, address indexed node, uint256 time);
event BeginBondReduction(address indexed minipool, uint256 time);
event CancelReductionVoted(address indexed minipool, address indexed member, uint256 time);
event ReductionCancelled(address indexed minipool, uint256 time);
constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
version = 3;
}
function getMinipoolCount() override public view returns (uint256) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
return addressSetStorage.getCount(keccak256(bytes("minipools.index")));
}
function getStakingMinipoolCount() override public view returns (uint256) {
return getUint(keccak256(bytes("minipools.staking.count")));
}
function getFinalisedMinipoolCount() override external view returns (uint256) {
return getUint(keccak256(bytes("minipools.finalised.count")));
}
function getActiveMinipoolCount() override public view returns (uint256) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
uint256 total = addressSetStorage.getCount(keccak256(bytes("minipools.index")));
uint256 finalised = getUint(keccak256(bytes("minipools.finalised.count")));
return total.sub(finalised);
}
function getMinipoolRPLSlashed(address _minipoolAddress) override external view returns (bool) {
return getBool(keccak256(abi.encodePacked("minipool.rpl.slashed", _minipoolAddress)));
}
function getMinipoolCountPerStatus(uint256 _offset, uint256 _limit) override external view
returns (uint256 initialisedCount, uint256 prelaunchCount, uint256 stakingCount, uint256 withdrawableCount, uint256 dissolvedCount) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
bytes32 minipoolKey = keccak256(abi.encodePacked("minipools.index"));
uint256 totalMinipools = getMinipoolCount();
uint256 max = _offset.add(_limit);
if (max > totalMinipools || _limit == 0) { max = totalMinipools; }
for (uint256 i = _offset; i < max; i++) {
RocketMinipoolInterface minipool = RocketMinipoolInterface(addressSetStorage.getItem(minipoolKey, i));
MinipoolStatus status = minipool.getStatus();
if (status == MinipoolStatus.Initialised) {
initialisedCount++;
}
else if (status == MinipoolStatus.Prelaunch) {
prelaunchCount++;
}
else if (status == MinipoolStatus.Staking) {
stakingCount++;
}
else if (status == MinipoolStatus.Withdrawable) {
withdrawableCount++;
}
else if (status == MinipoolStatus.Dissolved) {
dissolvedCount++;
}
}
}
function getPrelaunchMinipools(uint256 _offset, uint256 _limit) override external view
returns (address[] memory) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
bytes32 minipoolKey = keccak256(abi.encodePacked("minipools.index"));
uint256 totalMinipools = getMinipoolCount();
uint256 max = _offset.add(_limit);
if (max > totalMinipools || _limit == 0) { max = totalMinipools; }
address[] memory minipools = new address[](max.sub(_offset));
uint256 total = 0;
for (uint256 i = _offset; i < max; i++) {
RocketMinipoolInterface minipool = RocketMinipoolInterface(addressSetStorage.getItem(minipoolKey, i));
MinipoolStatus status = minipool.getStatus();
if (status == MinipoolStatus.Prelaunch) {
minipools[total] = address(minipool);
total++;
}
}
assembly {
mstore(minipools, total)
}
return minipools;
}
function getMinipoolAt(uint256 _index) override external view returns (address) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
return addressSetStorage.getItem(keccak256(abi.encodePacked("minipools.index")), _index);
}
function getNodeMinipoolCount(address _nodeAddress) override external view returns (uint256) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
return addressSetStorage.getCount(keccak256(abi.encodePacked("node.minipools.index", _nodeAddress)));
}
function getNodeActiveMinipoolCount(address _nodeAddress) override public view returns (uint256) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
uint256 finalised = getUint(keccak256(abi.encodePacked("node.minipools.finalised.count", _nodeAddress)));
uint256 total = addressSetStorage.getCount(keccak256(abi.encodePacked("node.minipools.index", _nodeAddress)));
return total.sub(finalised);
}
function getNodeFinalisedMinipoolCount(address _nodeAddress) override external view returns (uint256) {
return getUint(keccak256(abi.encodePacked("node.minipools.finalised.count", _nodeAddress)));
}
function getNodeStakingMinipoolCount(address _nodeAddress) override public view returns (uint256) {
RocketNodeDepositInterface rocketNodeDeposit = RocketNodeDepositInterface(getContractAddress("rocketNodeDeposit"));
uint256[] memory depositSizes = rocketNodeDeposit.getDepositAmounts();
uint256 total;
for (uint256 i = 0; i < depositSizes.length; i++){
total = total.add(getNodeStakingMinipoolCountBySize(_nodeAddress, depositSizes[i]));
}
return total;
}
function getNodeStakingMinipoolCountBySize(address _nodeAddress, uint256 _depositSize) override public view returns (uint256) {
bytes32 nodeKey;
if (_depositSize == 16 ether){
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", _nodeAddress));
} else {
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", _nodeAddress, _depositSize));
}
return getUint(nodeKey);
}
function getNodeMinipoolAt(address _nodeAddress, uint256 _index) override external view returns (address) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
return addressSetStorage.getItem(keccak256(abi.encodePacked("node.minipools.index", _nodeAddress)), _index);
}
function getNodeValidatingMinipoolCount(address _nodeAddress) override external view returns (uint256) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
return addressSetStorage.getCount(keccak256(abi.encodePacked("node.minipools.validating.index", _nodeAddress)));
}
function getNodeValidatingMinipoolAt(address _nodeAddress, uint256 _index) override external view returns (address) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
return addressSetStorage.getItem(keccak256(abi.encodePacked("node.minipools.validating.index", _nodeAddress)), _index);
}
function getMinipoolByPubkey(bytes memory _pubkey) override public view returns (address) {
return getAddress(keccak256(abi.encodePacked("validator.minipool", _pubkey)));
}
function getMinipoolExists(address _minipoolAddress) override public view returns (bool) {
return getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress)));
}
function getMinipoolDestroyed(address _minipoolAddress) override external view returns (bool) {
return getBool(keccak256(abi.encodePacked("minipool.destroyed", _minipoolAddress)));
}
function getMinipoolPubkey(address _minipoolAddress) override public view returns (bytes memory) {
return getBytes(keccak256(abi.encodePacked("minipool.pubkey", _minipoolAddress)));
}
function getMinipoolWithdrawalCredentials(address _minipoolAddress) override public pure returns (bytes memory) {
return abi.encodePacked(byte(0x01), bytes11(0x0), address(_minipoolAddress));
}
function updateNodeStakingMinipoolCount(uint256 _previousBond, uint256 _newBond, uint256 _previousFee, uint256 _newFee) override external onlyLatestContract("rocketMinipoolManager", address(this)) onlyRegisteredMinipool(msg.sender) {
bytes32 nodeKey;
bytes32 numeratorKey;
RocketMinipoolInterface minipool = RocketMinipoolInterface(msg.sender);
address nodeAddress = minipool.getNodeAddress();
_tryDistribute(nodeAddress);
if (_previousBond == 16 ether){
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", nodeAddress));
numeratorKey = keccak256(abi.encodePacked("node.average.fee.numerator", nodeAddress));
} else {
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", nodeAddress, _previousBond));
numeratorKey = keccak256(abi.encodePacked("node.average.fee.numerator", nodeAddress, _previousBond));
}
subUint(nodeKey, 1);
subUint(numeratorKey, _previousFee);
if (_newBond == 16 ether){
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", nodeAddress));
numeratorKey = keccak256(abi.encodePacked("node.average.fee.numerator", nodeAddress));
} else {
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", nodeAddress, _newBond));
numeratorKey = keccak256(abi.encodePacked("node.average.fee.numerator", nodeAddress, _newBond));
}
addUint(nodeKey, 1);
addUint(numeratorKey, _newFee);
}
function incrementNodeStakingMinipoolCount(address _nodeAddress) override external onlyLatestContract("rocketMinipoolManager", address(this)) onlyRegisteredMinipool(msg.sender) {
RocketMinipoolInterface minipool = RocketMinipoolInterface(msg.sender);
_tryDistribute(_nodeAddress);
uint256 depositSize = minipool.getNodeDepositBalance();
bytes32 nodeKey;
bytes32 numeratorKey;
if (depositSize == 16 ether){
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", _nodeAddress));
numeratorKey = keccak256(abi.encodePacked("node.average.fee.numerator", _nodeAddress));
} else {
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", _nodeAddress, depositSize));
numeratorKey = keccak256(abi.encodePacked("node.average.fee.numerator", _nodeAddress, depositSize));
}
uint256 nodeValue = getUint(nodeKey);
setUint(nodeKey, nodeValue.add(1));
bytes32 totalKey = keccak256(abi.encodePacked("minipools.staking.count"));
uint256 totalValue = getUint(totalKey);
setUint(totalKey, totalValue.add(1));
addUint(numeratorKey, minipool.getNodeFee());
}
function decrementNodeStakingMinipoolCount(address _nodeAddress) override external onlyLatestContract("rocketMinipoolManager", address(this)) onlyRegisteredMinipool(msg.sender) {
RocketMinipoolInterface minipool = RocketMinipoolInterface(msg.sender);
_tryDistribute(_nodeAddress);
uint256 depositSize = minipool.getNodeDepositBalance();
bytes32 nodeKey;
bytes32 numeratorKey;
if (depositSize == 16 ether){
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", _nodeAddress));
numeratorKey = keccak256(abi.encodePacked("node.average.fee.numerator", _nodeAddress));
} else {
nodeKey = keccak256(abi.encodePacked("node.minipools.staking.count", _nodeAddress, depositSize));
numeratorKey = keccak256(abi.encodePacked("node.average.fee.numerator", _nodeAddress, depositSize));
}
uint256 nodeValue = getUint(nodeKey);
setUint(nodeKey, nodeValue.sub(1));
bytes32 totalKey = keccak256(abi.encodePacked("minipools.staking.count"));
uint256 totalValue = getUint(totalKey);
setUint(totalKey, totalValue.sub(1));
subUint(numeratorKey, minipool.getNodeFee());
}
function _tryDistribute(address _nodeAddress) internal {
RocketNodeDistributorFactoryInterface rocketNodeDistributorFactory = RocketNodeDistributorFactoryInterface(getContractAddress("rocketNodeDistributorFactory"));
address distributorAddress = rocketNodeDistributorFactory.getProxyAddress(_nodeAddress);
if (distributorAddress.balance > 0) {
RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
require(rocketNodeManager.getFeeDistributorInitialised(_nodeAddress), "Distributor not initialised");
RocketNodeDistributorInterface distributor = RocketNodeDistributorInterface(distributorAddress);
distributor.distribute();
}
}
function incrementNodeFinalisedMinipoolCount(address _nodeAddress) override external onlyLatestContract("rocketMinipoolManager", address(this)) onlyRegisteredMinipool(msg.sender) {
bytes32 finalisedKey = keccak256(abi.encodePacked("node.minipools.finalised", msg.sender));
require(!getBool(finalisedKey), "Minipool has already been finalised");
setBool(finalisedKey, true);
addUint(keccak256(abi.encodePacked("node.minipools.finalised.count", _nodeAddress)), 1);
addUint(keccak256(bytes("minipools.finalised.count")), 1);
uint256 ethMatched = getUint(keccak256(abi.encodePacked("eth.matched.node.amount", _nodeAddress)));
if (ethMatched == 0) {
ethMatched = getNodeActiveMinipoolCount(_nodeAddress).mul(16 ether);
} else {
RocketMinipoolInterface minipool = RocketMinipoolInterface(msg.sender);
ethMatched = ethMatched.sub(minipool.getUserDepositBalance());
}
setUint(keccak256(abi.encodePacked("eth.matched.node.amount", _nodeAddress)), ethMatched);
}
function createMinipool(address _nodeAddress, uint256 _salt) override public onlyLatestContract("rocketMinipoolManager", address(this)) onlyLatestContract("rocketNodeDeposit", msg.sender) returns (RocketMinipoolInterface) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
{
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
uint256 totalMinipoolCount = getActiveMinipoolCount();
require(totalMinipoolCount.add(1) <= rocketDAOProtocolSettingsMinipool.getMaximumCount(), "Global minipool limit reached");
}
address contractAddress = deployContract(_nodeAddress, _salt);
setBool(keccak256(abi.encodePacked("minipool.exists", contractAddress)), true);
addressSetStorage.addItem(keccak256(abi.encodePacked("minipools.index")), contractAddress);
addressSetStorage.addItem(keccak256(abi.encodePacked("node.minipools.index", _nodeAddress)), contractAddress);
emit MinipoolCreated(contractAddress, _nodeAddress, block.timestamp);
return RocketMinipoolInterface(contractAddress);
}
function createVacantMinipool(address _nodeAddress, uint256 _salt, bytes calldata _validatorPubkey, uint256 _bondAmount, uint256 _currentBalance) override external onlyLatestContract("rocketMinipoolManager", address(this)) onlyLatestContract("rocketNodeDeposit", msg.sender) returns (RocketMinipoolInterface) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
RocketMinipoolInterface minipool = createMinipool(_nodeAddress, _salt);
minipool.prepareVacancy(_bondAmount, _currentBalance);
_setMinipoolPubkey(address(minipool), _validatorPubkey);
addressSetStorage.addItem(keccak256(abi.encodePacked("minipools.vacant.index")), address(minipool));
return minipool;
}
function removeVacantMinipool() override external onlyLatestContract("rocketMinipoolManager", address(this)) onlyRegisteredMinipool(msg.sender) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
addressSetStorage.removeItem(keccak256(abi.encodePacked("minipools.vacant.index")), msg.sender);
bytes memory pubkey = getMinipoolPubkey(msg.sender);
deleteAddress(keccak256(abi.encodePacked("validator.minipool", pubkey)));
}
function getVacantMinipoolCount() override external view returns (uint256) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
return addressSetStorage.getCount(keccak256(abi.encodePacked("minipools.vacant.index")));
}
function getVacantMinipoolAt(uint256 _index) override external view returns (address) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
return addressSetStorage.getItem(keccak256(abi.encodePacked("minipools.vacant.index")), _index);
}
function destroyMinipool() override external onlyLatestContract("rocketMinipoolManager", address(this)) onlyRegisteredMinipool(msg.sender) {
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
RocketMinipoolInterface minipool = RocketMinipoolInterface(msg.sender);
address nodeAddress = minipool.getNodeAddress();
uint256 ethMatched = getUint(keccak256(abi.encodePacked("eth.matched.node.amount", nodeAddress)));
if (ethMatched == 0) {
ethMatched = getNodeActiveMinipoolCount(nodeAddress).mul(16 ether);
}
if (minipool.getDepositType() == MinipoolDeposit.Variable) {
ethMatched = ethMatched.sub(minipool.getUserDepositBalance());
} else {
ethMatched = ethMatched.sub(16 ether);
}
setUint(keccak256(abi.encodePacked("eth.matched.node.amount", nodeAddress)), ethMatched);
setBool(keccak256(abi.encodePacked("minipool.exists", msg.sender)), false);
setBool(keccak256(abi.encodePacked("minipool.destroyed", msg.sender)), true);
addressSetStorage.removeItem(keccak256(abi.encodePacked("minipools.index")), msg.sender);
addressSetStorage.removeItem(keccak256(abi.encodePacked("node.minipools.index", nodeAddress)), msg.sender);
bytes memory pubkey = getMinipoolPubkey(msg.sender);
deleteBytes(keccak256(abi.encodePacked("minipool.pubkey", msg.sender)));
deleteAddress(keccak256(abi.encodePacked("validator.minipool", pubkey)));
emit MinipoolDestroyed(msg.sender, nodeAddress, block.timestamp);
}
function setMinipoolPubkey(bytes calldata _pubkey) override public onlyLatestContract("rocketMinipoolManager", address(this)) onlyRegisteredMinipool(msg.sender) {
_setMinipoolPubkey(msg.sender, _pubkey);
}
function _setMinipoolPubkey(address _minipool, bytes calldata _pubkey) private {
require(getMinipoolByPubkey(_pubkey) == address(0x0), "Validator pubkey is in use");
AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage"));
RocketMinipoolInterface minipool = RocketMinipoolInterface(_minipool);
address nodeAddress = minipool.getNodeAddress();
setBytes(keccak256(abi.encodePacked("minipool.pubkey", _minipool)), _pubkey);
setAddress(keccak256(abi.encodePacked("validator.minipool", _pubkey)), _minipool);
addressSetStorage.addItem(keccak256(abi.encodePacked("node.minipools.validating.index", nodeAddress)), _minipool);
}
function getMinipoolDepositType(address _minipoolAddress) external override view returns (MinipoolDeposit) {
RocketMinipoolInterface minipoolInterface = RocketMinipoolInterface(_minipoolAddress);
uint8 version = 1;
try minipoolInterface.version() returns (uint8 tryVersion) {
version = tryVersion;
} catch (bytes memory ) {}
if (version == 1 || version == 2) {
try minipoolInterface.getDepositType{gas: 30000}() returns (MinipoolDeposit depositType) {
return depositType;
} catch (bytes memory ) {
return MinipoolDeposit.Variable;
}
}
return minipoolInterface.getDepositType();
}
function deployContract(address _nodeAddress, uint256 _salt) private returns (address) {
RocketMinipoolFactoryInterface rocketMinipoolFactory = RocketMinipoolFactoryInterface(getContractAddress("rocketMinipoolFactory"));
return rocketMinipoolFactory.deployContract(_nodeAddress, _salt);
}
}
文件 21 的 35:RocketMinipoolManagerInterface.sol
pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;
import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolDetails.sol";
import "./RocketMinipoolInterface.sol";
interface RocketMinipoolManagerInterface {
function getMinipoolCount() external view returns (uint256);
function getStakingMinipoolCount() external view returns (uint256);
function getFinalisedMinipoolCount() external view returns (uint256);
function getActiveMinipoolCount() external view returns (uint256);
function getMinipoolRPLSlashed(address _minipoolAddress) external view returns (bool);
function getMinipoolCountPerStatus(uint256 offset, uint256 limit) external view returns (uint256, uint256, uint256, uint256, uint256);
function getPrelaunchMinipools(uint256 offset, uint256 limit) external view returns (address[] memory);
function getMinipoolAt(uint256 _index) external view returns (address);
function getNodeMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeActiveMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeFinalisedMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeStakingMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeStakingMinipoolCountBySize(address _nodeAddress, uint256 _depositSize) external view returns (uint256);
function getNodeMinipoolAt(address _nodeAddress, uint256 _index) external view returns (address);
function getNodeValidatingMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeValidatingMinipoolAt(address _nodeAddress, uint256 _index) external view returns (address);
function getMinipoolByPubkey(bytes calldata _pubkey) external view returns (address);
function getMinipoolExists(address _minipoolAddress) external view returns (bool);
function getMinipoolDestroyed(address _minipoolAddress) external view returns (bool);
function getMinipoolPubkey(address _minipoolAddress) external view returns (bytes memory);
function updateNodeStakingMinipoolCount(uint256 _previousBond, uint256 _newBond, uint256 _previousFee, uint256 _newFee) external;
function getMinipoolWithdrawalCredentials(address _minipoolAddress) external pure returns (bytes memory);
function createMinipool(address _nodeAddress, uint256 _salt) external returns (RocketMinipoolInterface);
function createVacantMinipool(address _nodeAddress, uint256 _salt, bytes calldata _validatorPubkey, uint256 _bondAmount, uint256 _currentBalance) external returns (RocketMinipoolInterface);
function removeVacantMinipool() external;
function getVacantMinipoolCount() external view returns (uint256);
function getVacantMinipoolAt(uint256 _index) external view returns (address);
function destroyMinipool() external;
function incrementNodeStakingMinipoolCount(address _nodeAddress) external;
function decrementNodeStakingMinipoolCount(address _nodeAddress) external;
function incrementNodeFinalisedMinipoolCount(address _nodeAddress) external;
function setMinipoolPubkey(bytes calldata _pubkey) external;
function getMinipoolDepositType(address _minipoolAddress) external view returns (MinipoolDeposit);
}
文件 22 的 35:RocketMinipoolPenaltyInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketMinipoolPenaltyInterface {
function setMaxPenaltyRate(uint256 _rate) external;
function getMaxPenaltyRate() external view returns (uint256);
function setPenaltyRate(address _minipoolAddress, uint256 _rate) external;
function getPenaltyRate(address _minipoolAddress) external view returns(uint256);
}
文件 23 的 35:RocketMinipoolQueueInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "../../types/MinipoolDeposit.sol";
interface RocketMinipoolQueueInterface {
function getTotalLength() external view returns (uint256);
function getContainsLegacy() external view returns (bool);
function getLengthLegacy(MinipoolDeposit _depositType) external view returns (uint256);
function getLength() external view returns (uint256);
function getTotalCapacity() external view returns (uint256);
function getEffectiveCapacity() external view returns (uint256);
function getNextCapacityLegacy() external view returns (uint256);
function getNextDepositLegacy() external view returns (MinipoolDeposit, uint256);
function enqueueMinipool(address _minipool) external;
function dequeueMinipoolByDepositLegacy(MinipoolDeposit _depositType) external returns (address minipoolAddress);
function dequeueMinipools(uint256 _maxToDequeue) external returns (address[] memory minipoolAddress);
function removeMinipool(MinipoolDeposit _depositType) external;
function getMinipoolAt(uint256 _index) external view returns(address);
function getMinipoolPosition(address _minipool) external view returns (int256);
}
文件 24 的 35:RocketMinipoolStorageLayout.sol
pragma solidity 0.7.6;
import "../../interface/RocketStorageInterface.sol";
import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolStatus.sol";
abstract contract RocketMinipoolStorageLayout {
enum StorageState {
Undefined,
Uninitialised,
Initialised
}
RocketStorageInterface internal rocketStorage = RocketStorageInterface(0);
MinipoolStatus internal status;
uint256 internal statusBlock;
uint256 internal statusTime;
uint256 internal withdrawalBlock;
MinipoolDeposit internal depositType;
address internal nodeAddress;
uint256 internal nodeFee;
uint256 internal nodeDepositBalance;
bool internal nodeDepositAssigned;
uint256 internal nodeRefundBalance;
uint256 internal nodeSlashBalance;
uint256 internal userDepositBalanceLegacy;
uint256 internal userDepositAssignedTime;
bool internal useLatestDelegate = false;
address internal rocketMinipoolDelegate;
address internal rocketMinipoolDelegatePrev;
address internal rocketTokenRETH;
address internal rocketMinipoolPenalty;
StorageState internal storageState = StorageState.Undefined;
bool internal finalised;
mapping(address => bool) internal memberScrubVotes;
uint256 internal totalScrubVotes;
uint256 internal preLaunchValue;
uint256 internal userDepositBalance;
bool internal vacant;
uint256 internal preMigrationBalance;
bool internal userDistributed;
uint256 internal userDistributeTime;
}
文件 25 的 35:RocketNetworkFeesInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketNetworkFeesInterface {
function getNodeDemand() external view returns (int256);
function getNodeFee() external view returns (uint256);
function getNodeFeeByDemand(int256 _nodeDemand) external view returns (uint256);
}
文件 26 的 35:RocketNetworkPenaltiesInterface.sol
pragma solidity 0.7.6;
interface RocketNetworkPenaltiesInterface {
function submitPenalty(address _minipoolAddress, uint256 _block) external;
function executeUpdatePenalty(address _minipoolAddress, uint256 _block) external;
function getPenaltyCount(address _minipoolAddress) external view returns (uint256);
}
文件 27 的 35:RocketNetworkPricesInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketNetworkPricesInterface {
function getPricesBlock() external view returns (uint256);
function getRPLPrice() external view returns (uint256);
function getLatestReportableBlock() external view returns (uint256);
function submitPrices(uint256 _block, uint256 _rplPrice) external;
function executeUpdatePrices(uint256 _block, uint256 _rplPrice) external;
}
文件 28 的 35:RocketNodeDepositInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "../../types/MinipoolDeposit.sol";
interface RocketNodeDepositInterface {
function getNodeDepositCredit(address _nodeOperator) external view returns (uint256);
function increaseDepositCreditBalance(address _nodeOperator, uint256 _amount) external;
function deposit(uint256 _depositAmount, uint256 _minimumNodeFee, bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot, uint256 _salt, address _expectedMinipoolAddress) external payable;
function depositWithCredit(uint256 _depositAmount, uint256 _minimumNodeFee, bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot, uint256 _salt, address _expectedMinipoolAddress) external payable;
function isValidDepositAmount(uint256 _amount) external pure returns (bool);
function getDepositAmounts() external pure returns (uint256[] memory);
function createVacantMinipool(uint256 _bondAmount, uint256 _minimumNodeFee, bytes calldata _validatorPubkey, uint256 _salt, address _expectedMinipoolAddress, uint256 _currentBalance) external;
function increaseEthMatched(address _nodeAddress, uint256 _amount) external;
}
文件 29 的 35:RocketNodeDistributorFactoryInterface.sol
pragma solidity 0.7.6;
interface RocketNodeDistributorFactoryInterface {
function getProxyBytecode() external pure returns (bytes memory);
function getProxyAddress(address _nodeAddress) external view returns(address);
function createProxy(address _nodeAddress) external;
}
文件 30 的 35:RocketNodeDistributorInterface.sol
pragma solidity 0.7.6;
interface RocketNodeDistributorInterface {
function getNodeShare() external view returns (uint256);
function getUserShare() external view returns (uint256);
function distribute() external;
}
文件 31 的 35:RocketNodeManagerInterface.sol
pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;
import "../../types/NodeDetails.sol";
interface RocketNodeManagerInterface {
struct TimezoneCount {
string timezone;
uint256 count;
}
function getNodeCount() external view returns (uint256);
function getNodeCountPerTimezone(uint256 offset, uint256 limit) external view returns (TimezoneCount[] memory);
function getNodeAt(uint256 _index) external view returns (address);
function getNodeExists(address _nodeAddress) external view returns (bool);
function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
function getNodeTimezoneLocation(address _nodeAddress) external view returns (string memory);
function registerNode(string calldata _timezoneLocation) external;
function getNodeRegistrationTime(address _nodeAddress) external view returns (uint256);
function setTimezoneLocation(string calldata _timezoneLocation) external;
function setRewardNetwork(address _nodeAddress, uint256 network) external;
function getRewardNetwork(address _nodeAddress) external view returns (uint256);
function getFeeDistributorInitialised(address _nodeAddress) external view returns (bool);
function initialiseFeeDistributor() external;
function getAverageNodeFee(address _nodeAddress) external view returns (uint256);
function setSmoothingPoolRegistrationState(bool _state) external;
function getSmoothingPoolRegistrationState(address _nodeAddress) external returns (bool);
function getSmoothingPoolRegistrationChanged(address _nodeAddress) external returns (uint256);
function getSmoothingPoolRegisteredNodeCount(uint256 _offset, uint256 _limit) external view returns (uint256);
function getNodeDetails(address _nodeAddress) external view returns (NodeDetails memory);
function getNodeAddresses(uint256 _offset, uint256 _limit) external view returns (address[] memory);
}
文件 32 的 35:RocketNodeStakingInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketNodeStakingInterface {
function getTotalRPLStake() external view returns (uint256);
function getNodeRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeETHMatched(address _nodeAddress) external view returns (uint256);
function getNodeETHProvided(address _nodeAddress) external view returns (uint256);
function getNodeETHCollateralisationRatio(address _nodeAddress) external view returns (uint256);
function getNodeRPLStakedTime(address _nodeAddress) external view returns (uint256);
function getNodeEffectiveRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeMinimumRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeMaximumRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeETHMatchedLimit(address _nodeAddress) external view returns (uint256);
function stakeRPL(uint256 _amount) external;
function stakeRPLFor(address _nodeAddress, uint256 _amount) external;
function setStakeRPLForAllowed(address _caller, bool _allowed) external;
function withdrawRPL(uint256 _amount) external;
function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) external;
}
文件 33 的 35:RocketStorageInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketStorageInterface {
function getDeployedStatus() external view returns (bool);
function getGuardian() external view returns(address);
function setGuardian(address _newAddress) external;
function confirmGuardian() external;
function getAddress(bytes32 _key) external view returns (address);
function getUint(bytes32 _key) external view returns (uint);
function getString(bytes32 _key) external view returns (string memory);
function getBytes(bytes32 _key) external view returns (bytes memory);
function getBool(bytes32 _key) external view returns (bool);
function getInt(bytes32 _key) external view returns (int);
function getBytes32(bytes32 _key) external view returns (bytes32);
function setAddress(bytes32 _key, address _value) external;
function setUint(bytes32 _key, uint _value) external;
function setString(bytes32 _key, string calldata _value) external;
function setBytes(bytes32 _key, bytes calldata _value) external;
function setBool(bytes32 _key, bool _value) external;
function setInt(bytes32 _key, int _value) external;
function setBytes32(bytes32 _key, bytes32 _value) external;
function deleteAddress(bytes32 _key) external;
function deleteUint(bytes32 _key) external;
function deleteString(bytes32 _key) external;
function deleteBytes(bytes32 _key) external;
function deleteBool(bytes32 _key) external;
function deleteInt(bytes32 _key) external;
function deleteBytes32(bytes32 _key) external;
function addUint(bytes32 _key, uint256 _amount) external;
function subUint(bytes32 _key, uint256 _amount) external;
function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
function setWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress, bool _confirm) external;
function confirmWithdrawalAddress(address _nodeAddress) external;
}
文件 34 的 35:RocketTokenRETHInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface RocketTokenRETHInterface is IERC20 {
function getEthValue(uint256 _rethAmount) external view returns (uint256);
function getRethValue(uint256 _ethAmount) external view returns (uint256);
function getExchangeRate() external view returns (uint256);
function getTotalCollateral() external view returns (uint256);
function getCollateralRate() external view returns (uint256);
function depositExcess() external payable;
function depositExcessCollateral() external;
function mint(uint256 _ethAmount, address _to) external;
function burn(uint256 _rethAmount) external;
}
文件 35 的 35:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"contracts/contract/minipool/RocketMinipoolManager.sol": "RocketMinipoolManager"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 15000
},
"remappings": []
}
[{"inputs":[{"internalType":"contract RocketStorageInterface","name":"_rocketStorageAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minipool","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"BeginBondReduction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minipool","type":"address"},{"indexed":true,"internalType":"address","name":"member","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"CancelReductionVoted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minipool","type":"address"},{"indexed":true,"internalType":"address","name":"node","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"MinipoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minipool","type":"address"},{"indexed":true,"internalType":"address","name":"node","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"MinipoolDestroyed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minipool","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"ReductionCancelled","type":"event"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_salt","type":"uint256"}],"name":"createMinipool","outputs":[{"internalType":"contract RocketMinipoolInterface","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_salt","type":"uint256"},{"internalType":"bytes","name":"_validatorPubkey","type":"bytes"},{"internalType":"uint256","name":"_bondAmount","type":"uint256"},{"internalType":"uint256","name":"_currentBalance","type":"uint256"}],"name":"createVacantMinipool","outputs":[{"internalType":"contract RocketMinipoolInterface","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"decrementNodeStakingMinipoolCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"destroyMinipool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getActiveMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFinalisedMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getMinipoolAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_pubkey","type":"bytes"}],"name":"getMinipoolByPubkey","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"getMinipoolCountPerStatus","outputs":[{"internalType":"uint256","name":"initialisedCount","type":"uint256"},{"internalType":"uint256","name":"prelaunchCount","type":"uint256"},{"internalType":"uint256","name":"stakingCount","type":"uint256"},{"internalType":"uint256","name":"withdrawableCount","type":"uint256"},{"internalType":"uint256","name":"dissolvedCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minipoolAddress","type":"address"}],"name":"getMinipoolDepositType","outputs":[{"internalType":"enum MinipoolDeposit","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minipoolAddress","type":"address"}],"name":"getMinipoolDestroyed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minipoolAddress","type":"address"}],"name":"getMinipoolExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minipoolAddress","type":"address"}],"name":"getMinipoolPubkey","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minipoolAddress","type":"address"}],"name":"getMinipoolRPLSlashed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minipoolAddress","type":"address"}],"name":"getMinipoolWithdrawalCredentials","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeActiveMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeFinalisedMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getNodeMinipoolAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeStakingMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_depositSize","type":"uint256"}],"name":"getNodeStakingMinipoolCountBySize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getNodeValidatingMinipoolAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeValidatingMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offset","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"getPrelaunchMinipools","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getVacantMinipoolAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVacantMinipoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"incrementNodeFinalisedMinipoolCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"incrementNodeStakingMinipoolCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeVacantMinipool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_pubkey","type":"bytes"}],"name":"setMinipoolPubkey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_previousBond","type":"uint256"},{"internalType":"uint256","name":"_newBond","type":"uint256"},{"internalType":"uint256","name":"_previousFee","type":"uint256"},{"internalType":"uint256","name":"_newFee","type":"uint256"}],"name":"updateNodeStakingMinipoolCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"}]