ETH Price: $2,532.40 (-1.62%)
Gas: 0.43 Gwei

Transaction Decoder

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 Code
0x1d8f8f00...b0ee0Fa46
(Rocket Pool: Storage)
(builder0x69)
0.270491887741211174 Eth0.271169659741211174 Eth0.000677772
0xe228017f...35bB4037C
(Rocket Pool: Node Distributor Factory)
0xE364e09c...1915342bf
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 1410600285864938084654749827923532205870162159010103973315917594929407466345165957803168047767456686540462142294146309992009455007047334134829613974888651545522861063259279464100833193630580728139439523858302556978422565344459395345991687226408118602957799105258282842318629932632444908587114375935050353708657320972469301902819584380486800678787057480664876744358765279469077323274578295538249753486908677599492942755180039633061906645447246564571831960476672599678970600816764630139036135472854964998263141528850457977462089653606855672726284107964330908277037042903154102971093747771947355496015857393793373451389281619068641148088357729979445122446475174901595506238203825477727696460316723
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 )
          File 1 of 6: RocketNodeManager
          // 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;
          }