Transaction Hash:
Block:
15725484 at Oct-11-2022 02:32:11 PM +UTC
Transaction Fee:
0.007908077704215024 ETH
$20.03
Gas Used:
338,886 Gas / 23.335510184 Gwei
Emitted Events:
171 |
RocketNodeDistributorFactory.ProxyCreated( _address=RocketNodeDistributor )
|
172 |
RocketNodeManager.NodeRegistered( node=[Sender] 0xfbed2f322c918363f6e663e00e923574027c5231, time=1665498731 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x1d8f8f00...b0ee0Fa46 | (Rocket Pool: Storage) | ||||
0x690B9A9E...Db4FaC990
Miner
| (builder0x69) | 0.270491887741211174 Eth | 0.271169659741211174 Eth | 0.000677772 | |
0xe228017f...35bB4037C | (Rocket Pool: Node Distributor Factory) | ||||
0xE364e09c...1915342bf |
0 Eth
Nonce: 0
|
0 Eth
Nonce: 1
| |||
0xFbEd2f32...4027C5231 |
5 Eth
Nonce: 0
|
4.992091922295784976 Eth
Nonce: 1
| 0.007908077704215024 |
Execution Trace
RocketNodeManager.registerNode( _timezoneLocation=Etc/UTC )
-
RocketStorage.getAddress( _key=AF00BE55C9FB8F543C04E0AA0D70351B880C1BFAFFFD15B60065A4A50C85EC94 ) => ( r=0x67CdE7AF920682A29fcfea1A179ef0f30F48Df3e )
-
RocketStorage.getAddress( _key=8CA4D6D0606CE014DF1D1195BF14AB56B1115C8AB25BF8C7D3EA96995ECD3DA3 ) => ( r=0xddB6E648D6cbeAB31A34a21cA5229db3FF16C9b6 )
-
RocketStorage.getAddress( _key=8B4D8AED962734B7D06D04F965F3793AD1BBF0A61133D3AD89386824B7A54B7B ) => ( r=0xD4ae2511dF21F367792bA4D67c6eb032171c6a16 )
RocketDAOProtocolSettingsNode.STATICCALL( )
-
RocketStorage.getBool( _key=F9FFFB46D6F9A7AAA54736AEF180CC68B56EFB736791D2CE1E121FCF9FC98C1C ) => ( r=True )
-
-
RocketStorage.setBool( _key=FCD0FD1CEC711A0FB836FFDD487A1F9C7912B008B9D50D926792337FB805C290, _value=True )
-
RocketStorage.setString( _key=04939CF65FE833AA6D47307BCD2F8CA2B8417504DC7C0D2399EF760910175584, _value=Etc/UTC )
AddressSetStorage.addItem( _key=B2FC74F0E3003FA42AC709F1C47D79ED4358E153EB2C56FEAB0A097A0F287705, _value=0xFbEd2f322c918363F6E663E00e923574027C5231 )
-
RocketStorage.getAddress( _key=8B4D8AED962734B7D06D04F965F3793AD1BBF0A61133D3AD89386824B7A54B7B ) => ( r=0xD4ae2511dF21F367792bA4D67c6eb032171c6a16 )
-
RocketStorage.getBool( _key=0AB5D37E1CEC93C2C6F91741A7B2A6BB01450E37DB7A2FD6024B34175A577855 ) => ( r=True )
-
RocketStorage.getUint( _key=3C778250286C84A2AE0CBDF4E2A1D0C6DC06FE05B14E15D71A7EB86127912CAF ) => ( r=0 )
-
RocketStorage.getUint( _key=2E762D2F256C577DCE20D4CE31DC2AF8C8DA2FA1B30F62E48051A488EFA751F7 ) => ( r=1614 )
-
RocketStorage.setAddress( _key=22598407BE2AC528FA8BFF47BF10B50379021C645C55AF05F4D624DB0B1C4E44, _value=0xFbEd2f322c918363F6E663E00e923574027C5231 )
-
RocketStorage.setUint( _key=3C778250286C84A2AE0CBDF4E2A1D0C6DC06FE05B14E15D71A7EB86127912CAF, _value=1615 )
-
RocketStorage.setUint( _key=2E762D2F256C577DCE20D4CE31DC2AF8C8DA2FA1B30F62E48051A488EFA751F7, _value=1615 )
-
-
RocketStorage.getAddress( _key=EA051094896EF3B09AB1B794AD5EA695A5FF3906F74A9328E2C16DB69D0F3123 ) => ( r=0xe228017f77B3E0785e794e4c0a8A6b935bB4037C )
RocketNodeDistributorFactory.createProxy( _nodeAddress=0xFbEd2f322c918363F6E663E00e923574027C5231 )
-
RocketStorage.getAddress( _key=AF00BE55C9FB8F543C04E0AA0D70351B880C1BFAFFFD15B60065A4A50C85EC94 ) => ( r=0x67CdE7AF920682A29fcfea1A179ef0f30F48Df3e )
-
RocketNodeDistributor.60a06040( )
-
-
RocketStorage.setUint( _key=33850747689F87DE62F6C6EB4DC2E383584843014F2D9954EA1FB817ECF4C395, _value=1665498731 )
registerNode[RocketNodeManager (ln:544)]
getContractAddress[RocketNodeManager (ln:546)]
getContractAddress[RocketNodeManager (ln:547)]
getRegistrationEnabled[RocketNodeManager (ln:549)]
setBool[RocketNodeManager (ln:553)]
setString[RocketNodeManager (ln:554)]
addItem[RocketNodeManager (ln:556)]
_initialiseFeeDistributor[RocketNodeManager (ln:558)]
getContractAddress[RocketNodeManager (ln:616)]
createProxy[RocketNodeManager (ln:618)]
setUint[RocketNodeManager (ln:560)]
NodeRegistered[RocketNodeManager (ln:562)]
File 1 of 6: RocketNodeManager
File 2 of 6: RocketNodeDistributorFactory
File 3 of 6: RocketStorage
File 4 of 6: RocketDAOProtocolSettingsNode
File 5 of 6: AddressSetStorage
File 6 of 6: RocketNodeDistributor
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ 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; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } } // SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../interface/RocketStorageInterface.sol"; /// @title Base settings / modifiers for each contract in Rocket Pool /// @author David Rugendyke abstract contract RocketBase { // Calculate using this as the base uint256 constant calcBase = 1 ether; // Version of the contract uint8 public version; // The main storage contract where primary persistant storage is maintained RocketStorageInterface rocketStorage = RocketStorageInterface(0); /*** Modifiers **********************************************************/ /** * @dev Throws if called by any sender that doesn't match a Rocket Pool network contract */ modifier onlyLatestNetworkContract() { require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract"); _; } /** * @dev Throws if called by any sender that doesn't match one of the supplied contract or is the latest version of that contract */ modifier onlyLatestContract(string memory _contractName, address _contractAddress) { require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract"); _; } /** * @dev Throws if called by any sender that isn't a registered node */ modifier onlyRegisteredNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node"); _; } /** * @dev Throws if called by any sender that isn't a trusted node DAO member */ modifier onlyTrustedNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node"); _; } /** * @dev Throws if called by any sender that isn't a registered minipool */ modifier onlyRegisteredMinipool(address _minipoolAddress) { require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool"); _; } /** * @dev Throws if called by any account other than a guardian account (temporary account allowed access to settings before DAO is fully enabled) */ modifier onlyGuardian() { require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian"); _; } /*** Methods **********************************************************/ /// @dev Set the main Rocket Storage address constructor(RocketStorageInterface _rocketStorageAddress) { // Update the contract address rocketStorage = RocketStorageInterface(_rocketStorageAddress); } /// @dev Get the address of a network contract by name function getContractAddress(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Check it require(contractAddress != address(0x0), "Contract not found"); // Return return contractAddress; } /// @dev Get the address of a network contract by name (returns address(0x0) instead of reverting if contract does not exist) function getContractAddressUnsafe(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Return return contractAddress; } /// @dev Get the name of a network contract by address function getContractName(address _contractAddress) internal view returns (string memory) { // Get the contract name string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress))); // Check it require(bytes(contractName).length > 0, "Contract not found"); // Return return contractName; } /// @dev Get revert error message from a .call method function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (_returnData.length < 68) return "Transaction reverted silently"; assembly { // Slice the sighash. _returnData := add(_returnData, 0x04) } return abi.decode(_returnData, (string)); // All that remains is the revert string } /*** Rocket Storage Methods ****************************************/ // Note: Unused helpers have been removed to keep contract sizes down /// @dev Storage get methods 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); } /// @dev Storage set methods 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); } /// @dev Storage delete methods 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); } /// @dev Storage arithmetic methods function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); } function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; pragma abicoder v2; // SPDX-License-Identifier: GPL-3.0-only import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../RocketBase.sol"; import "../../types/MinipoolStatus.sol"; import "../../types/NodeDetails.sol"; import "../../interface/node/RocketNodeManagerInterface.sol"; import "../../interface/rewards/claims/RocketClaimNodeInterface.sol"; import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol"; import "../../interface/util/AddressSetStorageInterface.sol"; import "../../interface/node/RocketNodeDistributorFactoryInterface.sol"; import "../../interface/minipool/RocketMinipoolManagerInterface.sol"; import "../../interface/node/RocketNodeDistributorInterface.sol"; import "../../interface/dao/node/settings/RocketDAONodeTrustedSettingsRewardsInterface.sol"; import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsRewardsInterface.sol"; import "../../interface/node/RocketNodeStakingInterface.sol"; // Node registration and management contract RocketNodeManager is RocketBase, RocketNodeManagerInterface { // Libraries using SafeMath for uint256; // Events event NodeRegistered(address indexed node, uint256 time); event NodeTimezoneLocationSet(address indexed node, uint256 time); event NodeRewardNetworkChanged(address indexed node, uint256 network); event NodeSmoothingPoolStateChanged(address indexed node, bool state); // Construct constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) { version = 2; } // Get the number of nodes in the network function getNodeCount() override public view returns (uint256) { AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage")); return addressSetStorage.getCount(keccak256(abi.encodePacked("nodes.index"))); } // Get a breakdown of the number of nodes per timezone function getNodeCountPerTimezone(uint256 _offset, uint256 _limit) override external view returns (TimezoneCount[] memory) { // Get contracts AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage")); // Precompute node key bytes32 nodeKey = keccak256(abi.encodePacked("nodes.index")); // Calculate range uint256 totalNodes = addressSetStorage.getCount(nodeKey); uint256 max = _offset.add(_limit); if (max > totalNodes || _limit == 0) { max = totalNodes; } // Create an array with as many elements as there are potential values to return TimezoneCount[] memory counts = new TimezoneCount[](max.sub(_offset)); uint256 uniqueTimezoneCount = 0; // Iterate the minipool range for (uint256 i = _offset; i < max; i++) { address nodeAddress = addressSetStorage.getItem(nodeKey, i); string memory timezone = getString(keccak256(abi.encodePacked("node.timezone.location", nodeAddress))); // Find existing entry in our array bool existing = false; for (uint256 j = 0; j < uniqueTimezoneCount; j++) { if (keccak256(bytes(counts[j].timezone)) == keccak256(bytes(timezone))) { existing = true; // Increment the counter counts[j].count++; break; } } // Entry was not found, so create a new one if (!existing) { counts[uniqueTimezoneCount].timezone = timezone; counts[uniqueTimezoneCount].count = 1; uniqueTimezoneCount++; } } // Dirty hack to cut unused elements off end of return value assembly { mstore(counts, uniqueTimezoneCount) } return counts; } // Get a node address by index function getNodeAt(uint256 _index) override external view returns (address) { AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage")); return addressSetStorage.getItem(keccak256(abi.encodePacked("nodes.index")), _index); } // Check whether a node exists function getNodeExists(address _nodeAddress) override public view returns (bool) { return getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))); } // Get a node's current withdrawal address function getNodeWithdrawalAddress(address _nodeAddress) override public view returns (address) { return rocketStorage.getNodeWithdrawalAddress(_nodeAddress); } // Get a node's pending withdrawal address function getNodePendingWithdrawalAddress(address _nodeAddress) override public view returns (address) { return rocketStorage.getNodePendingWithdrawalAddress(_nodeAddress); } // Get a node's timezone location function getNodeTimezoneLocation(address _nodeAddress) override public view returns (string memory) { return getString(keccak256(abi.encodePacked("node.timezone.location", _nodeAddress))); } // Register a new node with Rocket Pool function registerNode(string calldata _timezoneLocation) override external onlyLatestContract("rocketNodeManager", address(this)) { // Load contracts RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode")); AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage")); // Check node settings require(rocketDAOProtocolSettingsNode.getRegistrationEnabled(), "Rocket Pool node registrations are currently disabled"); // Check timezone location require(bytes(_timezoneLocation).length >= 4, "The timezone location is invalid"); // Initialise node data setBool(keccak256(abi.encodePacked("node.exists", msg.sender)), true); setString(keccak256(abi.encodePacked("node.timezone.location", msg.sender)), _timezoneLocation); // Add node to index addressSetStorage.addItem(keccak256(abi.encodePacked("nodes.index")), msg.sender); // Initialise fee distributor for this node _initialiseFeeDistributor(msg.sender); // Set node registration time (uses old storage key name for backwards compatibility) setUint(keccak256(abi.encodePacked("rewards.pool.claim.contract.registered.time", "rocketClaimNode", msg.sender)), block.timestamp); // Emit node registered event emit NodeRegistered(msg.sender, block.timestamp); } // Get's the timestamp of when a node was registered function getNodeRegistrationTime(address _nodeAddress) onlyRegisteredNode(_nodeAddress) override public view returns (uint256) { return getUint(keccak256(abi.encodePacked("rewards.pool.claim.contract.registered.time", "rocketClaimNode", _nodeAddress))); } // Set a node's timezone location // Only accepts calls from registered nodes function setTimezoneLocation(string calldata _timezoneLocation) override external onlyLatestContract("rocketNodeManager", address(this)) onlyRegisteredNode(msg.sender) { // Check timezone location require(bytes(_timezoneLocation).length >= 4, "The timezone location is invalid"); // Set timezone location setString(keccak256(abi.encodePacked("node.timezone.location", msg.sender)), _timezoneLocation); // Emit node timezone location set event emit NodeTimezoneLocationSet(msg.sender, block.timestamp); } // Returns true if node has initialised their fee distributor contract function getFeeDistributorInitialised(address _nodeAddress) override public view returns (bool) { // Load contracts RocketNodeDistributorFactoryInterface rocketNodeDistributorFactory = RocketNodeDistributorFactoryInterface(getContractAddress("rocketNodeDistributorFactory")); // Get distributor address address contractAddress = rocketNodeDistributorFactory.getProxyAddress(_nodeAddress); // Check if contract exists at that address uint32 codeSize; assembly { codeSize := extcodesize(contractAddress) } return codeSize > 0; } // Node operators created before the distributor was implemented must call this to setup their distributor contract function initialiseFeeDistributor() override external onlyLatestContract("rocketNodeManager", address(this)) onlyRegisteredNode(msg.sender) { // Prevent multiple calls require(!getFeeDistributorInitialised(msg.sender), "Already initialised"); // Load contracts RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager")); // Calculate and set current average fee numerator uint256 count = rocketMinipoolManager.getNodeMinipoolCount(msg.sender); if (count > 0){ uint256 numerator; // Note: this loop is safe as long as all current node operators at the time of upgrade have few enough minipools for (uint256 i = 0; i < count; i++) { RocketMinipoolInterface minipool = RocketMinipoolInterface(rocketMinipoolManager.getMinipoolAt(i)); if (minipool.getStatus() == MinipoolStatus.Staking){ numerator = numerator.add(minipool.getNodeFee()); } } setUint(keccak256(abi.encodePacked("node.average.fee.numerator", msg.sender)), numerator); } // Create the distributor contract _initialiseFeeDistributor(msg.sender); } // Deploys the fee distributor contract for a given node function _initialiseFeeDistributor(address _nodeAddress) internal { // Load contracts RocketNodeDistributorFactoryInterface rocketNodeDistributorFactory = RocketNodeDistributorFactoryInterface(getContractAddress("rocketNodeDistributorFactory")); // Create the distributor proxy rocketNodeDistributorFactory.createProxy(_nodeAddress); } // Calculates a nodes average node fee function getAverageNodeFee(address _nodeAddress) override external view returns (uint256) { // Load contracts RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager")); // Calculate average uint256 denominator = rocketMinipoolManager.getNodeStakingMinipoolCount(_nodeAddress); if (denominator == 0) { return 0; } uint256 numerator = getUint(keccak256(abi.encodePacked("node.average.fee.numerator", _nodeAddress))); return numerator.div(denominator); } // Designates which network a node would like their rewards relayed to function setRewardNetwork(address _nodeAddress, uint256 _network) override external onlyLatestContract("rocketNodeManager", address(this)) { // Confirm the transaction is from the node's current withdrawal address address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(_nodeAddress); require(withdrawalAddress == msg.sender, "Only a tx from a node's withdrawal address can change reward network"); // Check network is enabled RocketDAONodeTrustedSettingsRewardsInterface rocketDAONodeTrustedSettingsRewards = RocketDAONodeTrustedSettingsRewardsInterface(getContractAddress("rocketDAONodeTrustedSettingsRewards")); require(rocketDAONodeTrustedSettingsRewards.getNetworkEnabled(_network), "Network is not enabled"); // Set the network setUint(keccak256(abi.encodePacked("node.reward.network", _nodeAddress)), _network); // Emit event emit NodeRewardNetworkChanged(_nodeAddress, _network); } // Returns which network a node has designated as their desired reward network function getRewardNetwork(address _nodeAddress) override public view onlyLatestContract("rocketNodeManager", address(this)) returns (uint256) { return getUint(keccak256(abi.encodePacked("node.reward.network", _nodeAddress))); } // Allows a node to register or deregister from the smoothing pool function setSmoothingPoolRegistrationState(bool _state) override external onlyLatestContract("rocketNodeManager", address(this)) onlyRegisteredNode(msg.sender) { // Ensure registration is enabled RocketDAOProtocolSettingsNodeInterface daoSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode")); require(daoSettingsNode.getSmoothingPoolRegistrationEnabled(), "Smoothing pool registrations are not active"); // Precompute storage keys bytes32 changeKey = keccak256(abi.encodePacked("node.smoothing.pool.changed.time", msg.sender)); bytes32 stateKey = keccak256(abi.encodePacked("node.smoothing.pool.state", msg.sender)); // Get from the DAO settings RocketDAOProtocolSettingsRewardsInterface daoSettingsRewards = RocketDAOProtocolSettingsRewardsInterface(getContractAddress("rocketDAOProtocolSettingsRewards")); uint256 rewardInterval = daoSettingsRewards.getRewardsClaimIntervalTime(); // Ensure node operator has waited the required time uint256 lastChange = getUint(changeKey); require(block.timestamp >= lastChange.add(rewardInterval), "Not enough time has passed since changing state"); // Ensure state is actually changing require(getBool(stateKey) != _state, "Invalid state change"); // Update registration state setUint(changeKey, block.timestamp); setBool(stateKey, _state); // Emit state change event emit NodeSmoothingPoolStateChanged(msg.sender, _state); } // Returns whether a node is registered or not from the smoothing pool function getSmoothingPoolRegistrationState(address _nodeAddress) override public view returns (bool) { return getBool(keccak256(abi.encodePacked("node.smoothing.pool.state", _nodeAddress))); } // Returns the timestamp of when the node last changed their smoothing pool registration state function getSmoothingPoolRegistrationChanged(address _nodeAddress) override external view returns (uint256) { return getUint(keccak256(abi.encodePacked("node.smoothing.pool.changed.time", _nodeAddress))); } // Returns the sum of nodes that are registered for the smoothing pool between _offset and (_offset + _limit) function getSmoothingPoolRegisteredNodeCount(uint256 _offset, uint256 _limit) override external view returns (uint256) { // Get contracts AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage")); // Precompute node key bytes32 nodeKey = keccak256(abi.encodePacked("nodes.index")); // Iterate over the requested minipool range uint256 totalNodes = getNodeCount(); uint256 max = _offset.add(_limit); if (max > totalNodes || _limit == 0) { max = totalNodes; } uint256 count = 0; for (uint256 i = _offset; i < max; i++) { address nodeAddress = addressSetStorage.getItem(nodeKey, i); if (getSmoothingPoolRegistrationState(nodeAddress)) { count++; } } return count; } // Convenience function to return all on-chain details about a given node function getNodeDetails(address _nodeAddress) override external view returns (NodeDetails memory nodeDetails) { // Get contracts RocketNodeStakingInterface rocketNodeStaking = RocketNodeStakingInterface(getContractAddress("rocketNodeStaking")); RocketNodeDistributorFactoryInterface rocketNodeDistributorFactory = RocketNodeDistributorFactoryInterface(getContractAddress("rocketNodeDistributorFactory")); RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager")); IERC20 rocketTokenRETH = IERC20(getContractAddress("rocketTokenRETH")); IERC20 rocketTokenRPL = IERC20(getContractAddress("rocketTokenRPL")); IERC20 rocketTokenRPLFixedSupply = IERC20(getContractAddress("rocketTokenRPLFixedSupply")); // Node details nodeDetails.withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(_nodeAddress); nodeDetails.pendingWithdrawalAddress = rocketStorage.getNodePendingWithdrawalAddress(_nodeAddress); nodeDetails.exists = getNodeExists(_nodeAddress); nodeDetails.registrationTime = getNodeRegistrationTime(_nodeAddress); nodeDetails.timezoneLocation = getNodeTimezoneLocation(_nodeAddress); nodeDetails.feeDistributorInitialised = getFeeDistributorInitialised(_nodeAddress); nodeDetails.rewardNetwork = getRewardNetwork(_nodeAddress); // Staking details nodeDetails.rplStake = rocketNodeStaking.getNodeRPLStake(_nodeAddress); nodeDetails.effectiveRPLStake = rocketNodeStaking.getNodeEffectiveRPLStake(_nodeAddress); nodeDetails.minimumRPLStake = rocketNodeStaking.getNodeMinimumRPLStake(_nodeAddress); nodeDetails.maximumRPLStake = rocketNodeStaking.getNodeMaximumRPLStake(_nodeAddress); nodeDetails.minipoolLimit = rocketNodeStaking.getNodeMinipoolLimit(_nodeAddress); // Distributor details nodeDetails.feeDistributorAddress = rocketNodeDistributorFactory.getProxyAddress(_nodeAddress); // Minipool details nodeDetails.minipoolCount = rocketMinipoolManager.getNodeMinipoolCount(_nodeAddress); // Balance details nodeDetails.balanceETH = _nodeAddress.balance; nodeDetails.balanceRETH = rocketTokenRETH.balanceOf(_nodeAddress); nodeDetails.balanceRPL = rocketTokenRPL.balanceOf(_nodeAddress); nodeDetails.balanceOldRPL = rocketTokenRPLFixedSupply.balanceOf(_nodeAddress); } // Returns a slice of the node operator address set function getNodeAddresses(uint256 _offset, uint256 _limit) override external view returns (address[] memory) { // Get contracts AddressSetStorageInterface addressSetStorage = AddressSetStorageInterface(getContractAddress("addressSetStorage")); // Precompute node key bytes32 nodeKey = keccak256(abi.encodePacked("nodes.index")); // Iterate over the requested minipool range uint256 totalNodes = getNodeCount(); uint256 max = _offset.add(_limit); if (max > totalNodes || _limit == 0) { max = totalNodes; } // Create array big enough for every minipool address[] memory nodes = new address[](max.sub(_offset)); uint256 total = 0; for (uint256 i = _offset; i < max; i++) { nodes[total] = addressSetStorage.getItem(nodeKey, i); total++; } // Dirty hack to cut unused elements off end of return value assembly { mstore(nodes, total) } return nodes; } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketStorageInterface { // Deploy status function getDeployedStatus() external view returns (bool); // Guardian function getGuardian() external view returns(address); function setGuardian(address _newAddress) external; function confirmGuardian() external; // Getters 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); // Setters 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; // Deleters 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; // Arithmetic function addUint(bytes32 _key, uint256 _amount) external; function subUint(bytes32 _key, uint256 _amount) external; // Protected storage 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; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketDAONodeTrustedSettingsRewardsInterface { function initialise() external; function getNetworkEnabled(uint256 _network) external view returns (bool); } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketDAOProtocolSettingsNodeInterface { function getRegistrationEnabled() external view returns (bool); function getSmoothingPoolRegistrationEnabled() external view returns (bool); function getDepositEnabled() external view returns (bool); function getMinimumPerMinipoolStake() external view returns (uint256); function getMaximumPerMinipoolStake() external view returns (uint256); } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketDAOProtocolSettingsRewardsInterface { function setSettingRewardsClaimer(string memory _contractName, uint256 _perc) external; function getRewardsClaimerPerc(string memory _contractName) external view returns (uint256); function getRewardsClaimerPercTimeUpdated(string memory _contractName) external view returns (uint256); function getRewardsClaimersPercTotal() external view returns (uint256); function getRewardsClaimIntervalTime() external view returns (uint256); } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../../types/MinipoolDeposit.sol"; import "../../types/MinipoolStatus.sol"; import "../RocketStorageInterface.sol"; interface RocketMinipoolInterface { function initialise(address _nodeAddress, MinipoolDeposit _depositType) 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 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 nodeDeposit(bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot) external payable; function userDeposit() external payable; function distributeBalance() external; function distributeBalanceAndFinalise() external; function refund() external; function slash() external; function finalise() external; function canStake() external view returns (bool); function stake(bytes calldata _validatorSignature, bytes32 _depositDataRoot) external; function setWithdrawable() external; function dissolve() external; function close() external; function voteScrub() external; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; pragma abicoder v2; // SPDX-License-Identifier: GPL-3.0-only 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 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 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 getMinipoolWithdrawalCredentials(address _minipoolAddress) external pure returns (bytes memory); function createMinipool(address _nodeAddress, MinipoolDeposit _depositType, uint256 _salt) external returns (RocketMinipoolInterface); 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 getMinipoolDetails(address _minipoolAddress) external view returns (MinipoolDetails memory); } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketNodeDistributorFactoryInterface { function getProxyBytecode() external pure returns (bytes memory); function getProxyAddress(address _nodeAddress) external view returns(address); function createProxy(address _nodeAddress) external; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketNodeDistributorInterface { function distribute() external; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; pragma abicoder v2; // SPDX-License-Identifier: GPL-3.0-only import "../../types/NodeDetails.sol"; interface RocketNodeManagerInterface { // Structs 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); } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketNodeStakingInterface { function getTotalRPLStake() external view returns (uint256); function getNodeRPLStake(address _nodeAddress) external view returns (uint256); function getNodeRPLStakedTime(address _nodeAddress) external view returns (uint256); function getTotalEffectiveRPLStake() external view returns (uint256); function calculateTotalEffectiveRPLStake(uint256 offset, uint256 limit, uint256 rplPrice) 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 getNodeMinipoolLimit(address _nodeAddress) external view returns (uint256); function stakeRPL(uint256 _amount) external; function stakeRPLFor(address _nodeAddress, uint256 _amount) external; function withdrawRPL(uint256 _amount) external; function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) external; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketClaimNodeInterface { function getEnabled() external view returns (bool); function getClaimPossible(address _nodeAddress) external view returns (bool); function getClaimRewardsPerc(address _nodeAddress) external view returns (uint256); function getClaimRewardsAmount(address _nodeAddress) external view returns (uint256); function register(address _nodeAddress, bool _enable) external; function claim() external; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only 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; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only // Represents the type of deposits required by a minipool enum MinipoolDeposit { None, // Marks an invalid deposit type Full, // The minipool requires 32 ETH from the node operator, 16 ETH of which will be refinanced from user deposits Half, // The minipool required 16 ETH from the node operator to be matched with 16 ETH from user deposits Empty // The minipool requires 0 ETH from the node operator to be matched with 32 ETH from user deposits (trusted nodes only) } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "./MinipoolDeposit.sol"; import "./MinipoolStatus.sol"; // A struct containing all the information on-chain about a specific minipool 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; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only // Represents a minipool's status within the network enum MinipoolStatus { Initialised, // The minipool has been initialised and is awaiting a deposit of user ETH Prelaunch, // The minipool has enough ETH to begin staking and is awaiting launch by the node operator Staking, // The minipool is currently staking Withdrawable, // The minipool has become withdrawable on the beacon chain and can be withdrawn from by the node operator Dissolved // The minipool has been dissolved and its user deposited ETH has been returned to the deposit pool } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only // A struct containing all the information on-chain about a specific node struct NodeDetails { bool exists; uint256 registrationTime; string timezoneLocation; bool feeDistributorInitialised; address feeDistributorAddress; uint256 rewardNetwork; uint256 rplStake; uint256 effectiveRPLStake; uint256 minimumRPLStake; uint256 maximumRPLStake; uint256 minipoolLimit; uint256 minipoolCount; uint256 balanceETH; uint256 balanceRETH; uint256 balanceRPL; uint256 balanceOldRPL; address withdrawalAddress; address pendingWithdrawalAddress; bool smoothingPoolRegistrationState; uint256 smoothingPoolRegistrationChanged; }
File 2 of 6: RocketNodeDistributorFactory
/** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../interface/RocketStorageInterface.sol"; /// @title Base settings / modifiers for each contract in Rocket Pool /// @author David Rugendyke abstract contract RocketBase { // Calculate using this as the base uint256 constant calcBase = 1 ether; // Version of the contract uint8 public version; // The main storage contract where primary persistant storage is maintained RocketStorageInterface rocketStorage = RocketStorageInterface(0); /*** Modifiers **********************************************************/ /** * @dev Throws if called by any sender that doesn't match a Rocket Pool network contract */ modifier onlyLatestNetworkContract() { require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract"); _; } /** * @dev Throws if called by any sender that doesn't match one of the supplied contract or is the latest version of that contract */ modifier onlyLatestContract(string memory _contractName, address _contractAddress) { require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract"); _; } /** * @dev Throws if called by any sender that isn't a registered node */ modifier onlyRegisteredNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node"); _; } /** * @dev Throws if called by any sender that isn't a trusted node DAO member */ modifier onlyTrustedNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node"); _; } /** * @dev Throws if called by any sender that isn't a registered minipool */ modifier onlyRegisteredMinipool(address _minipoolAddress) { require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool"); _; } /** * @dev Throws if called by any account other than a guardian account (temporary account allowed access to settings before DAO is fully enabled) */ modifier onlyGuardian() { require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian"); _; } /*** Methods **********************************************************/ /// @dev Set the main Rocket Storage address constructor(RocketStorageInterface _rocketStorageAddress) { // Update the contract address rocketStorage = RocketStorageInterface(_rocketStorageAddress); } /// @dev Get the address of a network contract by name function getContractAddress(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Check it require(contractAddress != address(0x0), "Contract not found"); // Return return contractAddress; } /// @dev Get the address of a network contract by name (returns address(0x0) instead of reverting if contract does not exist) function getContractAddressUnsafe(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Return return contractAddress; } /// @dev Get the name of a network contract by address function getContractName(address _contractAddress) internal view returns (string memory) { // Get the contract name string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress))); // Check it require(bytes(contractName).length > 0, "Contract not found"); // Return return contractName; } /// @dev Get revert error message from a .call method function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (_returnData.length < 68) return "Transaction reverted silently"; assembly { // Slice the sighash. _returnData := add(_returnData, 0x04) } return abi.decode(_returnData, (string)); // All that remains is the revert string } /*** Rocket Storage Methods ****************************************/ // Note: Unused helpers have been removed to keep contract sizes down /// @dev Storage get methods 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); } /// @dev Storage set methods 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); } /// @dev Storage delete methods 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); } /// @dev Storage arithmetic methods function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); } function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../RocketBase.sol"; import "./RocketNodeDistributorStorageLayout.sol"; contract RocketNodeDistributor is RocketNodeDistributorStorageLayout { bytes32 immutable distributorStorageKey; constructor(address _nodeAddress, address _rocketStorage) { rocketStorage = RocketStorageInterface(_rocketStorage); nodeAddress = _nodeAddress; // Precompute storage key for rocketNodeDistributorDelegate distributorStorageKey = keccak256(abi.encodePacked("contract.address", "rocketNodeDistributorDelegate")); } // Allow contract to receive ETH without making a delegated call receive() external payable {} // Delegates all transactions to the target supplied during creation fallback() external payable { address _target = rocketStorage.getAddress(distributorStorageKey); assembly { calldatacopy(0x0, 0x0, calldatasize()) let result := delegatecall(gas(), _target, 0x0, calldatasize(), 0x0, 0) returndatacopy(0x0, 0x0, returndatasize()) switch result case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} } } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../RocketBase.sol"; import "./RocketNodeDistributor.sol"; import "./RocketNodeDistributorStorageLayout.sol"; import "../../interface/node/RocketNodeDistributorFactoryInterface.sol"; contract RocketNodeDistributorFactory is RocketBase, RocketNodeDistributorFactoryInterface { // Events event ProxyCreated(address _address); // Construct constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) { version = 1; } function getProxyBytecode() override public pure returns (bytes memory) { return type(RocketNodeDistributor).creationCode; } // Calculates the predetermined distributor contract address from given node address function getProxyAddress(address _nodeAddress) override external view returns(address) { bytes memory contractCode = getProxyBytecode(); bytes memory initCode = abi.encodePacked(contractCode, abi.encode(_nodeAddress, rocketStorage)); bytes32 hash = keccak256(abi.encodePacked(bytes1(0xff), address(this), uint256(0), keccak256(initCode))); return address(uint160(uint(hash))); } // Uses CREATE2 to deploy a RocketNodeDistributor at predetermined address function createProxy(address _nodeAddress) override external onlyLatestContract("rocketNodeManager", msg.sender) { // Salt is not required as the initCode is already unique per node address (node address is constructor argument) RocketNodeDistributor dist = new RocketNodeDistributor{salt: ''}(_nodeAddress, address(rocketStorage)); emit ProxyCreated(address(dist)); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; import "../../interface/RocketStorageInterface.sol"; // SPDX-License-Identifier: GPL-3.0-only abstract contract RocketNodeDistributorStorageLayout { RocketStorageInterface rocketStorage; address nodeAddress; }/** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketStorageInterface { // Deploy status function getDeployedStatus() external view returns (bool); // Guardian function getGuardian() external view returns(address); function setGuardian(address _newAddress) external; function confirmGuardian() external; // Getters 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); // Setters 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; // Deleters 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; // Arithmetic function addUint(bytes32 _key, uint256 _amount) external; function subUint(bytes32 _key, uint256 _amount) external; // Protected storage 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; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketNodeDistributorFactoryInterface { function getProxyBytecode() external pure returns (bytes memory); function getProxyAddress(address _nodeAddress) external view returns(address); function createProxy(address _nodeAddress) external; }
File 3 of 6: RocketStorage
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ 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; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to * be community-owned, decentralised, and trustless. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../interface/RocketStorageInterface.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; /// @title The primary persistent storage for Rocket Pool /// @author David Rugendyke contract RocketStorage is RocketStorageInterface { // Events event NodeWithdrawalAddressSet(address indexed node, address indexed withdrawalAddress, uint256 time); event GuardianChanged(address oldGuardian, address newGuardian); // Libraries using SafeMath for uint256; // Storage maps mapping(bytes32 => string) private stringStorage; mapping(bytes32 => bytes) private bytesStorage; mapping(bytes32 => uint256) private uintStorage; mapping(bytes32 => int256) private intStorage; mapping(bytes32 => address) private addressStorage; mapping(bytes32 => bool) private booleanStorage; mapping(bytes32 => bytes32) private bytes32Storage; // Protected storage (not accessible by network contracts) mapping(address => address) private withdrawalAddresses; mapping(address => address) private pendingWithdrawalAddresses; // Guardian address address guardian; address newGuardian; // Flag storage has been initialised bool storageInit = false; /// @dev Only allow access from the latest version of a contract in the Rocket Pool network after deployment modifier onlyLatestRocketNetworkContract() { if (storageInit == true) { // Make sure the access is permitted to only contracts in our Dapp require(booleanStorage[keccak256(abi.encodePacked("contract.exists", msg.sender))], "Invalid or outdated network contract"); } else { // Only Dapp and the guardian account are allowed access during initialisation. // tx.origin is only safe to use in this case for deployment since no external contracts are interacted with require(( booleanStorage[keccak256(abi.encodePacked("contract.exists", msg.sender))] || tx.origin == guardian ), "Invalid or outdated network contract attempting access during deployment"); } _; } /// @dev Construct RocketStorage constructor() { // Set the guardian upon deployment guardian = msg.sender; } // Get guardian address function getGuardian() external override view returns (address) { return guardian; } // Transfers guardianship to a new address function setGuardian(address _newAddress) external override { // Check tx comes from current guardian require(msg.sender == guardian, "Is not guardian account"); // Store new address awaiting confirmation newGuardian = _newAddress; } // Confirms change of guardian function confirmGuardian() external override { // Check tx came from new guardian address require(msg.sender == newGuardian, "Confirmation must come from new guardian address"); // Store old guardian for event address oldGuardian = guardian; // Update guardian and clear storage guardian = newGuardian; delete newGuardian; // Emit event emit GuardianChanged(oldGuardian, guardian); } // Set this as being deployed now function getDeployedStatus() external override view returns (bool) { return storageInit; } // Set this as being deployed now function setDeployedStatus() external { // Only guardian can lock this down require(msg.sender == guardian, "Is not guardian account"); // Set it now storageInit = true; } // Protected storage // Get a node's withdrawal address function getNodeWithdrawalAddress(address _nodeAddress) public override view returns (address) { // If no withdrawal address has been set, return the nodes address address withdrawalAddress = withdrawalAddresses[_nodeAddress]; if (withdrawalAddress == address(0)) { return _nodeAddress; } return withdrawalAddress; } // Get a node's pending withdrawal address function getNodePendingWithdrawalAddress(address _nodeAddress) external override view returns (address) { return pendingWithdrawalAddresses[_nodeAddress]; } // Set a node's withdrawal address function setWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress, bool _confirm) external override { // Check new withdrawal address require(_newWithdrawalAddress != address(0x0), "Invalid withdrawal address"); // Confirm the transaction is from the node's current withdrawal address address withdrawalAddress = getNodeWithdrawalAddress(_nodeAddress); require(withdrawalAddress == msg.sender, "Only a tx from a node's withdrawal address can update it"); // Update immediately if confirmed if (_confirm) { updateWithdrawalAddress(_nodeAddress, _newWithdrawalAddress); } // Set pending withdrawal address if not confirmed else { pendingWithdrawalAddresses[_nodeAddress] = _newWithdrawalAddress; } } // Confirm a node's new withdrawal address function confirmWithdrawalAddress(address _nodeAddress) external override { // Get node by pending withdrawal address require(pendingWithdrawalAddresses[_nodeAddress] == msg.sender, "Confirmation must come from the pending withdrawal address"); delete pendingWithdrawalAddresses[_nodeAddress]; // Update withdrawal address updateWithdrawalAddress(_nodeAddress, msg.sender); } // Update a node's withdrawal address function updateWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress) private { // Set new withdrawal address withdrawalAddresses[_nodeAddress] = _newWithdrawalAddress; // Emit withdrawal address set event emit NodeWithdrawalAddressSet(_nodeAddress, _newWithdrawalAddress, block.timestamp); } /// @param _key The key for the record function getAddress(bytes32 _key) override external view returns (address r) { return addressStorage[_key]; } /// @param _key The key for the record function getUint(bytes32 _key) override external view returns (uint256 r) { return uintStorage[_key]; } /// @param _key The key for the record function getString(bytes32 _key) override external view returns (string memory) { return stringStorage[_key]; } /// @param _key The key for the record function getBytes(bytes32 _key) override external view returns (bytes memory) { return bytesStorage[_key]; } /// @param _key The key for the record function getBool(bytes32 _key) override external view returns (bool r) { return booleanStorage[_key]; } /// @param _key The key for the record function getInt(bytes32 _key) override external view returns (int r) { return intStorage[_key]; } /// @param _key The key for the record function getBytes32(bytes32 _key) override external view returns (bytes32 r) { return bytes32Storage[_key]; } /// @param _key The key for the record function setAddress(bytes32 _key, address _value) onlyLatestRocketNetworkContract override external { addressStorage[_key] = _value; } /// @param _key The key for the record function setUint(bytes32 _key, uint _value) onlyLatestRocketNetworkContract override external { uintStorage[_key] = _value; } /// @param _key The key for the record function setString(bytes32 _key, string calldata _value) onlyLatestRocketNetworkContract override external { stringStorage[_key] = _value; } /// @param _key The key for the record function setBytes(bytes32 _key, bytes calldata _value) onlyLatestRocketNetworkContract override external { bytesStorage[_key] = _value; } /// @param _key The key for the record function setBool(bytes32 _key, bool _value) onlyLatestRocketNetworkContract override external { booleanStorage[_key] = _value; } /// @param _key The key for the record function setInt(bytes32 _key, int _value) onlyLatestRocketNetworkContract override external { intStorage[_key] = _value; } /// @param _key The key for the record function setBytes32(bytes32 _key, bytes32 _value) onlyLatestRocketNetworkContract override external { bytes32Storage[_key] = _value; } /// @param _key The key for the record function deleteAddress(bytes32 _key) onlyLatestRocketNetworkContract override external { delete addressStorage[_key]; } /// @param _key The key for the record function deleteUint(bytes32 _key) onlyLatestRocketNetworkContract override external { delete uintStorage[_key]; } /// @param _key The key for the record function deleteString(bytes32 _key) onlyLatestRocketNetworkContract override external { delete stringStorage[_key]; } /// @param _key The key for the record function deleteBytes(bytes32 _key) onlyLatestRocketNetworkContract override external { delete bytesStorage[_key]; } /// @param _key The key for the record function deleteBool(bytes32 _key) onlyLatestRocketNetworkContract override external { delete booleanStorage[_key]; } /// @param _key The key for the record function deleteInt(bytes32 _key) onlyLatestRocketNetworkContract override external { delete intStorage[_key]; } /// @param _key The key for the record function deleteBytes32(bytes32 _key) onlyLatestRocketNetworkContract override external { delete bytes32Storage[_key]; } /// @param _key The key for the record /// @param _amount An amount to add to the record's value function addUint(bytes32 _key, uint256 _amount) onlyLatestRocketNetworkContract override external { uintStorage[_key] = uintStorage[_key].add(_amount); } /// @param _key The key for the record /// @param _amount An amount to subtract from the record's value function subUint(bytes32 _key, uint256 _amount) onlyLatestRocketNetworkContract override external { uintStorage[_key] = uintStorage[_key].sub(_amount); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to * be community-owned, decentralised, and trustless. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketStorageInterface { // Deploy status function getDeployedStatus() external view returns (bool); // Guardian function getGuardian() external view returns(address); function setGuardian(address _newAddress) external; function confirmGuardian() external; // Getters 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); // Setters 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; // Deleters 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; // Arithmetic function addUint(bytes32 _key, uint256 _amount) external; function subUint(bytes32 _key, uint256 _amount) external; // Protected storage 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; }
File 4 of 6: RocketDAOProtocolSettingsNode
/** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../interface/RocketStorageInterface.sol"; /// @title Base settings / modifiers for each contract in Rocket Pool /// @author David Rugendyke abstract contract RocketBase { // Calculate using this as the base uint256 constant calcBase = 1 ether; // Version of the contract uint8 public version; // The main storage contract where primary persistant storage is maintained RocketStorageInterface rocketStorage = RocketStorageInterface(0); /*** Modifiers **********************************************************/ /** * @dev Throws if called by any sender that doesn't match a Rocket Pool network contract */ modifier onlyLatestNetworkContract() { require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract"); _; } /** * @dev Throws if called by any sender that doesn't match one of the supplied contract or is the latest version of that contract */ modifier onlyLatestContract(string memory _contractName, address _contractAddress) { require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract"); _; } /** * @dev Throws if called by any sender that isn't a registered node */ modifier onlyRegisteredNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node"); _; } /** * @dev Throws if called by any sender that isn't a trusted node DAO member */ modifier onlyTrustedNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node"); _; } /** * @dev Throws if called by any sender that isn't a registered minipool */ modifier onlyRegisteredMinipool(address _minipoolAddress) { require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool"); _; } /** * @dev Throws if called by any account other than a guardian account (temporary account allowed access to settings before DAO is fully enabled) */ modifier onlyGuardian() { require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian"); _; } /*** Methods **********************************************************/ /// @dev Set the main Rocket Storage address constructor(RocketStorageInterface _rocketStorageAddress) { // Update the contract address rocketStorage = RocketStorageInterface(_rocketStorageAddress); } /// @dev Get the address of a network contract by name function getContractAddress(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Check it require(contractAddress != address(0x0), "Contract not found"); // Return return contractAddress; } /// @dev Get the address of a network contract by name (returns address(0x0) instead of reverting if contract does not exist) function getContractAddressUnsafe(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Return return contractAddress; } /// @dev Get the name of a network contract by address function getContractName(address _contractAddress) internal view returns (string memory) { // Get the contract name string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress))); // Check it require(bytes(contractName).length > 0, "Contract not found"); // Return return contractName; } /// @dev Get revert error message from a .call method function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (_returnData.length < 68) return "Transaction reverted silently"; assembly { // Slice the sighash. _returnData := add(_returnData, 0x04) } return abi.decode(_returnData, (string)); // All that remains is the revert string } /*** Rocket Storage Methods ****************************************/ // Note: Unused helpers have been removed to keep contract sizes down /// @dev Storage get methods 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); } /// @dev Storage set methods 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); } /// @dev Storage delete methods 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); } /// @dev Storage arithmetic methods function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); } function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../../../RocketBase.sol"; import "../../../../interface/dao/protocol/settings/RocketDAOProtocolSettingsInterface.sol"; // Settings in RP which the DAO will have full control over // This settings contract enables storage using setting paths with namespaces, rather than explicit set methods abstract contract RocketDAOProtocolSettings is RocketBase, RocketDAOProtocolSettingsInterface { // The namespace for a particular group of settings bytes32 settingNameSpace; // Only allow updating from the DAO proposals contract modifier onlyDAOProtocolProposal() { // If this contract has been initialised, only allow access from the proposals contract if(getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")))) require(getContractAddress("rocketDAOProtocolProposals") == msg.sender, "Only DAO Protocol Proposals contract can update a setting"); _; } // Construct constructor(RocketStorageInterface _rocketStorageAddress, string memory _settingNameSpace) RocketBase(_rocketStorageAddress) { // Apply the setting namespace settingNameSpace = keccak256(abi.encodePacked("dao.protocol.setting.", _settingNameSpace)); } /*** Uints ****************/ // A general method to return any setting given the setting path is correct, only accepts uints function getSettingUint(string memory _settingPath) public view override returns (uint256) { return getUint(keccak256(abi.encodePacked(settingNameSpace, _settingPath))); } // Update a Uint setting, can only be executed by the DAO contract when a majority on a setting proposal has passed and been executed function setSettingUint(string memory _settingPath, uint256 _value) virtual public override onlyDAOProtocolProposal { // Update setting now setUint(keccak256(abi.encodePacked(settingNameSpace, _settingPath)), _value); } /*** Bools ****************/ // A general method to return any setting given the setting path is correct, only accepts bools function getSettingBool(string memory _settingPath) public view override returns (bool) { return getBool(keccak256(abi.encodePacked(settingNameSpace, _settingPath))); } // Update a setting, can only be executed by the DAO contract when a majority on a setting proposal has passed and been executed function setSettingBool(string memory _settingPath, bool _value) virtual public override onlyDAOProtocolProposal { // Update setting now setBool(keccak256(abi.encodePacked(settingNameSpace, _settingPath)), _value); } /*** Addresses ****************/ // A general method to return any setting given the setting path is correct, only accepts addresses function getSettingAddress(string memory _settingPath) external view override returns (address) { return getAddress(keccak256(abi.encodePacked(settingNameSpace, _settingPath))); } // Update a setting, can only be executed by the DAO contract when a majority on a setting proposal has passed and been executed function setSettingAddress(string memory _settingPath, address _value) virtual external override onlyDAOProtocolProposal { // Update setting now setAddress(keccak256(abi.encodePacked(settingNameSpace, _settingPath)), _value); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "./RocketDAOProtocolSettings.sol"; import "../../../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol"; // Network auction settings contract RocketDAOProtocolSettingsNode is RocketDAOProtocolSettings, RocketDAOProtocolSettingsNodeInterface { // Construct constructor(RocketStorageInterface _rocketStorageAddress) RocketDAOProtocolSettings(_rocketStorageAddress, "node") { // Set version version = 2; // Initialize settings on deployment if(!getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")))) { // Apply settings setSettingBool("node.registration.enabled", false); setSettingBool("node.smoothing.pool.registration.enabled", false); setSettingBool("node.deposit.enabled", false); setSettingUint("node.per.minipool.stake.minimum", 0.1 ether); // 10% of user ETH value setSettingUint("node.per.minipool.stake.maximum", 1.5 ether); // 150% of user ETH value // Settings initialised setBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")), true); } } // Node registrations currently enabled function getRegistrationEnabled() override external view returns (bool) { return getSettingBool("node.registration.enabled"); } // Node smoothing pool registrations currently enabled function getSmoothingPoolRegistrationEnabled() override external view returns (bool) { return getSettingBool("node.smoothing.pool.registration.enabled"); } // Node deposits currently enabled function getDepositEnabled() override external view returns (bool) { return getSettingBool("node.deposit.enabled"); } // Minimum RPL stake per minipool as a fraction of assigned user ETH value function getMinimumPerMinipoolStake() override external view returns (uint256) { return getSettingUint("node.per.minipool.stake.minimum"); } // Maximum RPL stake per minipool as a fraction of assigned user ETH value function getMaximumPerMinipoolStake() override external view returns (uint256) { return getSettingUint("node.per.minipool.stake.maximum"); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketStorageInterface { // Deploy status function getDeployedStatus() external view returns (bool); // Guardian function getGuardian() external view returns(address); function setGuardian(address _newAddress) external; function confirmGuardian() external; // Getters 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); // Setters 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; // Deleters 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; // Arithmetic function addUint(bytes32 _key, uint256 _amount) external; function subUint(bytes32 _key, uint256 _amount) external; // Protected storage 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; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketDAOProtocolSettingsInterface { function getSettingUint(string memory _settingPath) external view returns (uint256); function setSettingUint(string memory _settingPath, uint256 _value) external; function getSettingBool(string memory _settingPath) external view returns (bool); function setSettingBool(string memory _settingPath, bool _value) external; function getSettingAddress(string memory _settingPath) external view returns (address); function setSettingAddress(string memory _settingPath, address _value) external; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketDAOProtocolSettingsNodeInterface { function getRegistrationEnabled() external view returns (bool); function getSmoothingPoolRegistrationEnabled() external view returns (bool); function getDepositEnabled() external view returns (bool); function getMinimumPerMinipoolStake() external view returns (uint256); function getMaximumPerMinipoolStake() external view returns (uint256); }
File 5 of 6: AddressSetStorage
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ 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; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to * be community-owned, decentralised, and trustless. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../interface/RocketStorageInterface.sol"; /// @title Base settings / modifiers for each contract in Rocket Pool /// @author David Rugendyke abstract contract RocketBase { // Calculate using this as the base uint256 constant calcBase = 1 ether; // Version of the contract uint8 public version; // The main storage contract where primary persistant storage is maintained RocketStorageInterface rocketStorage = RocketStorageInterface(0); /*** Modifiers **********************************************************/ /** * @dev Throws if called by any sender that doesn't match a Rocket Pool network contract */ modifier onlyLatestNetworkContract() { require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract"); _; } /** * @dev Throws if called by any sender that doesn't match one of the supplied contract or is the latest version of that contract */ modifier onlyLatestContract(string memory _contractName, address _contractAddress) { require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract"); _; } /** * @dev Throws if called by any sender that isn't a registered node */ modifier onlyRegisteredNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node"); _; } /** * @dev Throws if called by any sender that isn't a trusted node DAO member */ modifier onlyTrustedNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node"); _; } /** * @dev Throws if called by any sender that isn't a registered minipool */ modifier onlyRegisteredMinipool(address _minipoolAddress) { require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool"); _; } /** * @dev Throws if called by any account other than a guardian account (temporary account allowed access to settings before DAO is fully enabled) */ modifier onlyGuardian() { require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian"); _; } /*** Methods **********************************************************/ /// @dev Set the main Rocket Storage address constructor(RocketStorageInterface _rocketStorageAddress) { // Update the contract address rocketStorage = RocketStorageInterface(_rocketStorageAddress); } /// @dev Get the address of a network contract by name function getContractAddress(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Check it require(contractAddress != address(0x0), "Contract not found"); // Return return contractAddress; } /// @dev Get the address of a network contract by name (returns address(0x0) instead of reverting if contract does not exist) function getContractAddressUnsafe(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Return return contractAddress; } /// @dev Get the name of a network contract by address function getContractName(address _contractAddress) internal view returns (string memory) { // Get the contract name string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress))); // Check it require(bytes(contractName).length > 0, "Contract not found"); // Return return contractName; } /// @dev Get revert error message from a .call method function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (_returnData.length < 68) return "Transaction reverted silently"; assembly { // Slice the sighash. _returnData := add(_returnData, 0x04) } return abi.decode(_returnData, (string)); // All that remains is the revert string } /*** Rocket Storage Methods ****************************************/ // Note: Unused helpers have been removed to keep contract sizes down /// @dev Storage get methods 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); } /// @dev Storage set methods 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); } /// @dev Storage delete methods 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); } /// @dev Storage arithmetic methods function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); } function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to * be community-owned, decentralised, and trustless. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../RocketBase.sol"; import "../../interface/util/AddressSetStorageInterface.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; // Address set storage helper for RocketStorage data (contains unique items; has reverse index lookups) contract AddressSetStorage is RocketBase, AddressSetStorageInterface { using SafeMath for uint; // Construct constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) { version = 1; } // The number of items in a set function getCount(bytes32 _key) override external view returns (uint) { return getUint(keccak256(abi.encodePacked(_key, ".count"))); } // The item in a set by index function getItem(bytes32 _key, uint _index) override external view returns (address) { return getAddress(keccak256(abi.encodePacked(_key, ".item", _index))); } // The index of an item in a set // Returns -1 if the value is not found function getIndexOf(bytes32 _key, address _value) override external view returns (int) { return int(getUint(keccak256(abi.encodePacked(_key, ".index", _value)))) - 1; } // Add an item to a set // Requires that the item does not exist in the set function addItem(bytes32 _key, address _value) override external onlyLatestContract("addressSetStorage", address(this)) onlyLatestNetworkContract { require(getUint(keccak256(abi.encodePacked(_key, ".index", _value))) == 0, "Item already exists in set"); uint count = getUint(keccak256(abi.encodePacked(_key, ".count"))); setAddress(keccak256(abi.encodePacked(_key, ".item", count)), _value); setUint(keccak256(abi.encodePacked(_key, ".index", _value)), count.add(1)); setUint(keccak256(abi.encodePacked(_key, ".count")), count.add(1)); } // Remove an item from a set // Swaps the item with the last item in the set and truncates it; computationally cheap // Requires that the item exists in the set function removeItem(bytes32 _key, address _value) override external onlyLatestContract("addressSetStorage", address(this)) onlyLatestNetworkContract { uint256 index = getUint(keccak256(abi.encodePacked(_key, ".index", _value))); require(index-- > 0, "Item does not exist in set"); uint count = getUint(keccak256(abi.encodePacked(_key, ".count"))); if (index < count.sub(1)) { address lastItem = getAddress(keccak256(abi.encodePacked(_key, ".item", count.sub(1)))); setAddress(keccak256(abi.encodePacked(_key, ".item", index)), lastItem); setUint(keccak256(abi.encodePacked(_key, ".index", lastItem)), index.add(1)); } setUint(keccak256(abi.encodePacked(_key, ".index", _value)), 0); setUint(keccak256(abi.encodePacked(_key, ".count")), count.sub(1)); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to * be community-owned, decentralised, and trustless. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only interface RocketStorageInterface { // Deploy status function getDeployedStatus() external view returns (bool); // Guardian function getGuardian() external view returns(address); function setGuardian(address _newAddress) external; function confirmGuardian() external; // Getters 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); // Setters 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; // Deleters 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; // Arithmetic function addUint(bytes32 _key, uint256 _amount) external; function subUint(bytes32 _key, uint256 _amount) external; // Protected storage 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; } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to * be community-owned, decentralised, and trustless. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only 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; }
File 6 of 6: RocketNodeDistributor
/** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../interface/RocketStorageInterface.sol"; /// @title Base settings / modifiers for each contract in Rocket Pool /// @author David Rugendyke abstract contract RocketBase { // Calculate using this as the base uint256 constant calcBase = 1 ether; // Version of the contract uint8 public version; // The main storage contract where primary persistant storage is maintained RocketStorageInterface rocketStorage = RocketStorageInterface(0); /*** Modifiers **********************************************************/ /** * @dev Throws if called by any sender that doesn't match a Rocket Pool network contract */ modifier onlyLatestNetworkContract() { require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract"); _; } /** * @dev Throws if called by any sender that doesn't match one of the supplied contract or is the latest version of that contract */ modifier onlyLatestContract(string memory _contractName, address _contractAddress) { require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract"); _; } /** * @dev Throws if called by any sender that isn't a registered node */ modifier onlyRegisteredNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node"); _; } /** * @dev Throws if called by any sender that isn't a trusted node DAO member */ modifier onlyTrustedNode(address _nodeAddress) { require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node"); _; } /** * @dev Throws if called by any sender that isn't a registered minipool */ modifier onlyRegisteredMinipool(address _minipoolAddress) { require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool"); _; } /** * @dev Throws if called by any account other than a guardian account (temporary account allowed access to settings before DAO is fully enabled) */ modifier onlyGuardian() { require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian"); _; } /*** Methods **********************************************************/ /// @dev Set the main Rocket Storage address constructor(RocketStorageInterface _rocketStorageAddress) { // Update the contract address rocketStorage = RocketStorageInterface(_rocketStorageAddress); } /// @dev Get the address of a network contract by name function getContractAddress(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Check it require(contractAddress != address(0x0), "Contract not found"); // Return return contractAddress; } /// @dev Get the address of a network contract by name (returns address(0x0) instead of reverting if contract does not exist) function getContractAddressUnsafe(string memory _contractName) internal view returns (address) { // Get the current contract address address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName))); // Return return contractAddress; } /// @dev Get the name of a network contract by address function getContractName(address _contractAddress) internal view returns (string memory) { // Get the contract name string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress))); // Check it require(bytes(contractName).length > 0, "Contract not found"); // Return return contractName; } /// @dev Get revert error message from a .call method function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) { // If the _res length is less than 68, then the transaction failed silently (without a revert message) if (_returnData.length < 68) return "Transaction reverted silently"; assembly { // Slice the sighash. _returnData := add(_returnData, 0x04) } return abi.decode(_returnData, (string)); // All that remains is the revert string } /*** Rocket Storage Methods ****************************************/ // Note: Unused helpers have been removed to keep contract sizes down /// @dev Storage get methods 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); } /// @dev Storage set methods 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); } /// @dev Storage delete methods 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); } /// @dev Storage arithmetic methods function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); } function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; // SPDX-License-Identifier: GPL-3.0-only import "../RocketBase.sol"; import "./RocketNodeDistributorStorageLayout.sol"; contract RocketNodeDistributor is RocketNodeDistributorStorageLayout { bytes32 immutable distributorStorageKey; constructor(address _nodeAddress, address _rocketStorage) { rocketStorage = RocketStorageInterface(_rocketStorage); nodeAddress = _nodeAddress; // Precompute storage key for rocketNodeDistributorDelegate distributorStorageKey = keccak256(abi.encodePacked("contract.address", "rocketNodeDistributorDelegate")); } // Allow contract to receive ETH without making a delegated call receive() external payable {} // Delegates all transactions to the target supplied during creation fallback() external payable { address _target = rocketStorage.getAddress(distributorStorageKey); assembly { calldatacopy(0x0, 0x0, calldatasize()) let result := delegatecall(gas(), _target, 0x0, calldatasize(), 0x0, 0) returndatacopy(0x0, 0x0, returndatasize()) switch result case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} } } } /** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity 0.7.6; import "../../interface/RocketStorageInterface.sol"; // SPDX-License-Identifier: GPL-3.0-only abstract contract RocketNodeDistributorStorageLayout { RocketStorageInterface rocketStorage; address nodeAddress; }/** * . * / \\ * |.'.| * |'.'| * ,'| |`. * |,-'-|-'-.| * __|_| | _ _ _____ _ * | ___ \\| | | | | | ___ \\ | | * | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | | * | // _ \\ / __| |/ / _ \\ __| | __/ _ \\ / _ \\| | * | |\\ \\ (_) | (__| < __/ |_ | | | (_) | (_) | | * \\_| \\_\\___/ \\___|_|\\_\\___|\\__| \\_| \\___/ \\___/|_| * +---------------------------------------------------+ * | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0 | * +---------------------------------------------------+ * * Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned, * decentralised, trustless and compatible with staking in Ethereum 2.0. * * For more information about Rocket Pool, visit https://rocketpool.net * * Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty * */ pragma solidity >0.5.0 <0.9.0; // SPDX-License-Identifier: GPL-3.0-only interface RocketStorageInterface { // Deploy status function getDeployedStatus() external view returns (bool); // Guardian function getGuardian() external view returns(address); function setGuardian(address _newAddress) external; function confirmGuardian() external; // Getters 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); // Setters 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; // Deleters 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; // Arithmetic function addUint(bytes32 _key, uint256 _amount) external; function subUint(bytes32 _key, uint256 _amount) external; // Protected storage 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; }