ETH Price: $3,841.31 (+2.35%)

Transaction Decoder

Block:
13578882 at Nov-09-2021 12:08:36 AM +UTC
Transaction Fee:
0.03469245433920515 ETH $133.26
Gas Used:
248,474 Gas / 139.622070475 Gwei

Emitted Events:

180 RocketNodeManager.NodeRegistered( node=[Sender] 0x724158f27466bf57c71adea8299b0a713d84e3f2, time=1636416516 )

Account State Difference:

  Address   Before After State Difference Code
0x1d8f8f00...b0ee0Fa46
(Rocket Pool: Storage)
0x724158F2...13d84E3f2
(Rocket Pool: Eth2 Depositor 1274)
0.666 Eth
Nonce: 0
0.63130754566079485 Eth
Nonce: 1
0.03469245433920515
(F2Pool Old)
4,450.852607028242004427 Eth4,450.852979739242004427 Eth0.000372711

Execution Trace

RocketNodeManager.registerNode( _timezoneLocation=Europe/Berlin )
  • RocketStorage.getAddress( _key=AF00BE55C9FB8F543C04E0AA0D70351B880C1BFAFFFD15B60065A4A50C85EC94 ) => ( r=0x4477Fbf4Af5b34E49662d9217681a763dDc0a322 )
  • RocketStorage.getAddress( _key=2DA3B61EEE74E043B820256E614F716340E1C8EAE64F70BC04208F9880E0E8A5 ) => ( r=0x899336A2a86053705E65dB61f52C686dcFaeF548 )
  • RocketStorage.getAddress( _key=8CA4D6D0606CE014DF1D1195BF14AB56B1115C8AB25BF8C7D3EA96995ECD3DA3 ) => ( r=0xc82D37221940b6E594d6D26D2c5aF775c3F1f437 )
  • RocketStorage.getAddress( _key=8B4D8AED962734B7D06D04F965F3793AD1BBF0A61133D3AD89386824B7A54B7B ) => ( r=0xD4ae2511dF21F367792bA4D67c6eb032171c6a16 )
  • RocketDAOProtocolSettingsNode.STATICCALL( )
    • RocketStorage.getBool( _key=F9FFFB46D6F9A7AAA54736AEF180CC68B56EFB736791D2CE1E121FCF9FC98C1C ) => ( r=True )
    • RocketStorage.setBool( _key=91BC34AAFB40B62593920B99E48509F985D040EA5DD192AA479B97B5FF6EF10E, _value=True )
    • RocketStorage.setString( _key=339075AF1F42A37B324BF9CE46BBC20D26635094A89B2CFE4EEB6D13A0669AA7, _value=Europe/Berlin )
    • AddressSetStorage.addItem( _key=B2FC74F0E3003FA42AC709F1C47D79ED4358E153EB2C56FEAB0A097A0F287705, _value=0x724158F27466BF57C71AdeA8299B0a713d84E3f2 )
      • RocketStorage.getAddress( _key=8B4D8AED962734B7D06D04F965F3793AD1BBF0A61133D3AD89386824B7A54B7B ) => ( r=0xD4ae2511dF21F367792bA4D67c6eb032171c6a16 )
      • RocketStorage.getBool( _key=39652E3F569D370F23726D0C8CD4BC5D87492B8D07647D1CBB8C3D0F8C355478 ) => ( r=True )
      • RocketStorage.getUint( _key=5FF75D1D84D4C20E62FF78EF0F9E2D3EA6A8B2F1237439EDB5C3191B96EDA387 ) => ( r=0 )
      • RocketStorage.getUint( _key=2E762D2F256C577DCE20D4CE31DC2AF8C8DA2FA1B30F62E48051A488EFA751F7 ) => ( r=11 )
      • RocketStorage.setAddress( _key=1CEB41F6CCD407000499B36FBF52484D9C61BD4C307F6FBD0AA99D87165FFB78, _value=0x724158F27466BF57C71AdeA8299B0a713d84E3f2 )
      • RocketStorage.setUint( _key=5FF75D1D84D4C20E62FF78EF0F9E2D3EA6A8B2F1237439EDB5C3191B96EDA387, _value=12 )
      • RocketStorage.setUint( _key=2E762D2F256C577DCE20D4CE31DC2AF8C8DA2FA1B30F62E48051A488EFA751F7, _value=12 )
      • RocketClaimNode.register( _nodeAddress=0x724158F27466BF57C71AdeA8299B0a713d84E3f2, _enable=True )
        • RocketStorage.getAddress( _key=2DA3B61EEE74E043B820256E614F716340E1C8EAE64F70BC04208F9880E0E8A5 ) => ( r=0x899336A2a86053705E65dB61f52C686dcFaeF548 )
        • RocketStorage.getAddress( _key=AF00BE55C9FB8F543C04E0AA0D70351B880C1BFAFFFD15B60065A4A50C85EC94 ) => ( r=0x4477Fbf4Af5b34E49662d9217681a763dDc0a322 )
        • RocketStorage.getBool( _key=91BC34AAFB40B62593920B99E48509F985D040EA5DD192AA479B97B5FF6EF10E ) => ( r=True )
        • RocketStorage.getAddress( _key=46C2B81204BF2F9DAD36168C4AA8891F039200535328E7DA10BB73514970FAE4 ) => ( r=0xA3a18348e6E2d3897B6f2671bb8c120e36554802 )
        • RocketRewardsPool.registerClaimer( _claimerAddress=0x724158F27466BF57C71AdeA8299B0a713d84E3f2, _enabled=True )
          • RocketStorage.getString( _key=FD9ABFF6A4D1ECB6B09EDE8FBD5E34CB40FD0B86288DFFDF975BDD3192D84E0F ) => ( rocketClaimNode )
          • RocketStorage.getAddress( _key=3AD4F859A8131D0F6F1460405F2F1AE75831E5545F71F91A5125524636E35E53 ) => ( r=0xCDb681AF33C60f4D659d12E309b6C57fA4A97673 )
          • RocketDAOProtocolSettingsRewards.getRewardsClaimerPercTimeUpdated( _contractName=rocketClaimNode ) => ( 1632980535 )
            • RocketStorage.getUint( _key=5FE8E563028B03DC2AE1E434574F86742EBD91C3F0BB5A4F5DE20D1B157D6F0C ) => ( r=1632980535 )
            • RocketStorage.getString( _key=FD9ABFF6A4D1ECB6B09EDE8FBD5E34CB40FD0B86288DFFDF975BDD3192D84E0F ) => ( rocketClaimNode )
            • RocketStorage.getUint( _key=00DE85DFD171C0BA02F3DA19B55582AAC5BFA61A55D494AC7BA63C759D09EF40 ) => ( r=11 )
            • RocketStorage.getUint( _key=67F8D088F6642B99223DFF5D94577E4A51002BA36B85C5E5D0B3A14E4B4873F1 ) => ( r=0 )
            • RocketStorage.setUint( _key=00DE85DFD171C0BA02F3DA19B55582AAC5BFA61A55D494AC7BA63C759D09EF40, _value=12 )
            • RocketStorage.setUint( _key=67F8D088F6642B99223DFF5D94577E4A51002BA36B85C5E5D0B3A14E4B4873F1, _value=1636416516 )
              File 1 of 7: 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;
                  }
              }
              /**
                *       .
                *      / \\
                *     |.'.|
                *     |'.'|
                *   ,'|   |`.
                *  |,-'-|-'-.|
                *   __|_| |         _        _      _____           _
                *  | ___ \\|        | |      | |    | ___ \\         | |
                *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                * +---------------------------------------------------+
                * |    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;
              pragma abicoder v2;
              // SPDX-License-Identifier: GPL-3.0-only
              import "@openzeppelin/contracts/math/SafeMath.sol";
              import "../RocketBase.sol";
              import "../../interface/node/RocketNodeManagerInterface.sol";
              import "../../interface/rewards/claims/RocketClaimNodeInterface.sol";
              import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol"; 
              import "../../interface/util/AddressSetStorageInterface.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);
                  // Construct
                  constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
                      version = 1;
                  }
                  // Get the number of nodes in the network
                  function getNodeCount() override external 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 external view returns (bool) {
                      return getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress)));
                  }
                  // Get a node's current withdrawal address
                  function getNodeWithdrawalAddress(address _nodeAddress) override external view returns (address) {
                      return rocketStorage.getNodeWithdrawalAddress(_nodeAddress);
                  }
                  // Get a node's pending withdrawal address
                  function getNodePendingWithdrawalAddress(address _nodeAddress) override external view returns (address) {
                      return rocketStorage.getNodePendingWithdrawalAddress(_nodeAddress);
                  }
                  // Get a node's timezone location
                  function getNodeTimezoneLocation(address _nodeAddress) override external 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
                      RocketClaimNodeInterface rocketClaimNode = RocketClaimNodeInterface(getContractAddress("rocketClaimNode"));
                      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);
                      // Register node for RPL claims
                      rocketClaimNode.register(msg.sender, true);
                      // Emit node registered event
                      emit NodeRegistered(msg.sender, block.timestamp);
                  }
                  // 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);
                  }
              }
              /**
                *       .
                *      / \\
                *     |.'.|
                *     |'.'|
                *   ,'|   |`.
                *  |,-'-|-'-.|
                *   __|_| |         _        _      _____           _
                *  | ___ \\|        | |      | |    | ___ \\         | |
                *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                * +---------------------------------------------------+
                * |    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 RocketDAOProtocolSettingsNodeInterface {
                  function getRegistrationEnabled() 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    |
                * +---------------------------------------------------+
                *
                *  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;
              pragma abicoder v2;
              // SPDX-License-Identifier: GPL-3.0-only
              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 setTimezoneLocation(string calldata _timezoneLocation) 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 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    |
                * +---------------------------------------------------+
                *
                *  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 2 of 7: 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 3 of 7: RocketDAOProtocolSettingsNode
              /**
                *       .
                *      / \\
                *     |.'.|
                *     |'.'|
                *   ,'|   |`.
                *  |,-'-|-'-.|
                *   __|_| |         _        _      _____           _
                *  | ___ \\|        | |      | |    | ___ \\         | |
                *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                * +---------------------------------------------------+
                * |    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/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    |
                * +---------------------------------------------------+
                *
                *  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 "./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 = 1;
                      // Initialize settings on deployment
                      if(!getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")))) {
                          // Apply settings
                          setSettingBool("node.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 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    |
                * +---------------------------------------------------+
                *
                *  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 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    |
                * +---------------------------------------------------+
                *
                *  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 RocketDAOProtocolSettingsNodeInterface {
                  function getRegistrationEnabled() external view returns (bool);
                  function getDepositEnabled() external view returns (bool);
                  function getMinimumPerMinipoolStake() external view returns (uint256);
                  function getMaximumPerMinipoolStake() external view returns (uint256);
              }
              

              File 4 of 7: 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 5 of 7: RocketClaimNode
              // 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 "@openzeppelin/contracts/math/SafeMath.sol";
              import "../../RocketBase.sol";
              import "../../../interface/node/RocketNodeManagerInterface.sol";
              import "../../../interface/node/RocketNodeStakingInterface.sol";
              import "../../../interface/rewards/RocketRewardsPoolInterface.sol";
              import "../../../interface/rewards/claims/RocketClaimNodeInterface.sol";
              // RPL Rewards claiming for regular nodes
              contract RocketClaimNode is RocketBase, RocketClaimNodeInterface {
                  // Libs
                  using SafeMath for uint;
                  // Construct
                  constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
                      version = 1;
                  }
                  // Get whether the contract is enabled for claims
                  function getEnabled() override external view returns (bool) {
                      RocketRewardsPoolInterface rocketRewardsPool = RocketRewardsPoolInterface(getContractAddress("rocketRewardsPool"));
                      return rocketRewardsPool.getClaimingContractEnabled("rocketClaimNode");
                  }
                  // Get whether a node can make a claim
                  function getClaimPossible(address _nodeAddress) override public view onlyRegisteredNode(_nodeAddress) returns (bool) {
                      // Load contracts
                      RocketRewardsPoolInterface rocketRewardsPool = RocketRewardsPoolInterface(getContractAddress("rocketRewardsPool"));
                      RocketNodeStakingInterface rocketNodeStaking = RocketNodeStakingInterface(getContractAddress("rocketNodeStaking"));
                      // Return claim possible status
                      return (
                          rocketRewardsPool.getClaimingContractUserCanClaim("rocketClaimNode", _nodeAddress) &&
                          rocketNodeStaking.getNodeRPLStake(_nodeAddress) >= rocketNodeStaking.getNodeMinimumRPLStake(_nodeAddress)
                      );
                  }
                  // Get the share of rewards for a node as a fraction of 1 ether
                  function getClaimRewardsPerc(address _nodeAddress) override public view onlyRegisteredNode(_nodeAddress) returns (uint256) {
                      // Check node can claim
                      if (!getClaimPossible(_nodeAddress)) { return 0; }
                      // Load contracts
                      RocketNodeStakingInterface rocketNodeStaking = RocketNodeStakingInterface(getContractAddress("rocketNodeStaking"));
                      // Calculate and return share
                      uint256 totalRplStake = rocketNodeStaking.getTotalEffectiveRPLStake();
                      if (totalRplStake == 0) { return 0; }
                      return calcBase.mul(rocketNodeStaking.getNodeEffectiveRPLStake(_nodeAddress)).div(totalRplStake);
                  }
                  // Get the amount of rewards for a node for the reward period
                  function getClaimRewardsAmount(address _nodeAddress) override external view onlyRegisteredNode(_nodeAddress) returns (uint256) {
                      RocketRewardsPoolInterface rocketRewardsPool = RocketRewardsPoolInterface(getContractAddress("rocketRewardsPool"));
                      return rocketRewardsPool.getClaimAmount("rocketClaimNode", _nodeAddress, getClaimRewardsPerc(_nodeAddress));
                  }
                  // Register or deregister a node for RPL claims
                  // Only accepts calls from the RocketNodeManager contract
                  function register(address _nodeAddress, bool _enable) override external onlyLatestContract("rocketClaimNode", address(this)) onlyLatestContract("rocketNodeManager", msg.sender) onlyRegisteredNode(_nodeAddress) {
                      RocketRewardsPoolInterface rocketRewardsPool = RocketRewardsPoolInterface(getContractAddress("rocketRewardsPool"));
                      rocketRewardsPool.registerClaimer(_nodeAddress, _enable);
                  }
                  // Make an RPL claim
                  // Only accepts calls from registered nodes
                  function claim() override external onlyLatestContract("rocketClaimNode", address(this)) onlyRegisteredNode(msg.sender) {
                      // Check that the node can claim
                      require(getClaimPossible(msg.sender), "The node is currently unable to claim");
                      // Get node withdrawal address
                      RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
                      address nodeWithdrawalAddress = rocketNodeManager.getNodeWithdrawalAddress(msg.sender);
                      // Claim RPL
                      RocketRewardsPoolInterface rocketRewardsPool = RocketRewardsPoolInterface(getContractAddress("rocketRewardsPool"));
                      rocketRewardsPool.claim(msg.sender, nodeWithdrawalAddress, getClaimRewardsPerc(msg.sender));
                  }
              }
              /**
                *       .
                *      / \\
                *     |.'.|
                *     |'.'|
                *   ,'|   |`.
                *  |,-'-|-'-.|
                *   __|_| |         _        _      _____           _
                *  | ___ \\|        | |      | |    | ___ \\         | |
                *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                * +---------------------------------------------------+
                * |    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;
              pragma abicoder v2;
              // SPDX-License-Identifier: GPL-3.0-only
              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 setTimezoneLocation(string calldata _timezoneLocation) 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 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 withdrawRPL(uint256 _amount) external;
                  function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) 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 RocketRewardsPoolInterface {
                  function getRPLBalance() external view returns(uint256);
                  function getClaimIntervalTimeStart() external view returns(uint256);
                  function getClaimIntervalTimeStartComputed() external view returns(uint256);
                  function getClaimIntervalsPassed() external view returns(uint256);
                  function getClaimIntervalTime() external view returns(uint256);
                  function getClaimTimeLastMade() external view returns(uint256);
                  function getClaimIntervalRewardsTotal() external view returns(uint256);
                  function getClaimingContractTotalClaimed(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractUserTotalNext(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractUserTotalCurrent(string memory _claimingContract) external view returns(uint256);  
                  function getClaimingContractUserHasClaimed(uint256 _claimIntervalStartTime, string memory _claimingContract, address _claimerAddress) external view returns(bool);
                  function getClaimingContractUserCanClaim(string memory _claimingContract, address _claimerAddress) external view returns(bool);
                  function getClaimingContractUserRegisteredTime(string memory _claimingContract, address _claimerAddress) external view returns(uint256);
                  function getClaimingContractAllowance(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractPerc(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractPercLast(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractExists(string memory _contractName) external view returns (bool);
                  function getClaimingContractEnabled(string memory _contractName) external view returns (bool);
                  function getClaimAmount(string memory _claimingContract, address _claimerAddress, uint256 _claimerAmountPerc) external view returns (uint256);
                  function registerClaimer(address _claimerAddress, bool _enabled) external;
                  function claim(address _claimerAddress, address _toAddress, uint256 _claimerAmount) 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 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;
              }
              

              File 6 of 7: RocketRewardsPool
              // 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;
              import "../../utils/Context.sol";
              import "./IERC20.sol";
              import "../../math/SafeMath.sol";
              /**
               * @dev Implementation of the {IERC20} interface.
               *
               * This implementation is agnostic to the way tokens are created. This means
               * that a supply mechanism has to be added in a derived contract using {_mint}.
               * For a generic mechanism see {ERC20PresetMinterPauser}.
               *
               * TIP: For a detailed writeup see our guide
               * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
               * to implement supply mechanisms].
               *
               * We have followed general OpenZeppelin guidelines: functions revert instead
               * of returning `false` on failure. This behavior is nonetheless conventional
               * and does not conflict with the expectations of ERC20 applications.
               *
               * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
               * This allows applications to reconstruct the allowance for all accounts just
               * by listening to said events. Other implementations of the EIP may not emit
               * these events, as it isn't required by the specification.
               *
               * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
               * functions have been added to mitigate the well-known issues around setting
               * allowances. See {IERC20-approve}.
               */
              contract ERC20 is Context, IERC20 {
                  using SafeMath for uint256;
                  mapping (address => uint256) private _balances;
                  mapping (address => mapping (address => uint256)) private _allowances;
                  uint256 private _totalSupply;
                  string private _name;
                  string private _symbol;
                  uint8 private _decimals;
                  /**
                   * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
                   * a default value of 18.
                   *
                   * To select a different value for {decimals}, use {_setupDecimals}.
                   *
                   * All three of these values are immutable: they can only be set once during
                   * construction.
                   */
                  constructor (string memory name_, string memory symbol_) public {
                      _name = name_;
                      _symbol = symbol_;
                      _decimals = 18;
                  }
                  /**
                   * @dev Returns the name of the token.
                   */
                  function name() public view virtual returns (string memory) {
                      return _name;
                  }
                  /**
                   * @dev Returns the symbol of the token, usually a shorter version of the
                   * name.
                   */
                  function symbol() public view virtual returns (string memory) {
                      return _symbol;
                  }
                  /**
                   * @dev Returns the number of decimals used to get its user representation.
                   * For example, if `decimals` equals `2`, a balance of `505` tokens should
                   * be displayed to a user as `5,05` (`505 / 10 ** 2`).
                   *
                   * Tokens usually opt for a value of 18, imitating the relationship between
                   * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
                   * called.
                   *
                   * NOTE: This information is only used for _display_ purposes: it in
                   * no way affects any of the arithmetic of the contract, including
                   * {IERC20-balanceOf} and {IERC20-transfer}.
                   */
                  function decimals() public view virtual returns (uint8) {
                      return _decimals;
                  }
                  /**
                   * @dev See {IERC20-totalSupply}.
                   */
                  function totalSupply() public view virtual override returns (uint256) {
                      return _totalSupply;
                  }
                  /**
                   * @dev See {IERC20-balanceOf}.
                   */
                  function balanceOf(address account) public view virtual override returns (uint256) {
                      return _balances[account];
                  }
                  /**
                   * @dev See {IERC20-transfer}.
                   *
                   * Requirements:
                   *
                   * - `recipient` cannot be the zero address.
                   * - the caller must have a balance of at least `amount`.
                   */
                  function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
                      _transfer(_msgSender(), recipient, amount);
                      return true;
                  }
                  /**
                   * @dev See {IERC20-allowance}.
                   */
                  function allowance(address owner, address spender) public view virtual override returns (uint256) {
                      return _allowances[owner][spender];
                  }
                  /**
                   * @dev See {IERC20-approve}.
                   *
                   * Requirements:
                   *
                   * - `spender` cannot be the zero address.
                   */
                  function approve(address spender, uint256 amount) public virtual override returns (bool) {
                      _approve(_msgSender(), spender, amount);
                      return true;
                  }
                  /**
                   * @dev See {IERC20-transferFrom}.
                   *
                   * Emits an {Approval} event indicating the updated allowance. This is not
                   * required by the EIP. See the note at the beginning of {ERC20}.
                   *
                   * Requirements:
                   *
                   * - `sender` and `recipient` cannot be the zero address.
                   * - `sender` must have a balance of at least `amount`.
                   * - the caller must have allowance for ``sender``'s tokens of at least
                   * `amount`.
                   */
                  function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
                      _transfer(sender, recipient, amount);
                      _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
                      return true;
                  }
                  /**
                   * @dev Atomically increases the allowance granted to `spender` by the caller.
                   *
                   * This is an alternative to {approve} that can be used as a mitigation for
                   * problems described in {IERC20-approve}.
                   *
                   * Emits an {Approval} event indicating the updated allowance.
                   *
                   * Requirements:
                   *
                   * - `spender` cannot be the zero address.
                   */
                  function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
                      _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
                      return true;
                  }
                  /**
                   * @dev Atomically decreases the allowance granted to `spender` by the caller.
                   *
                   * This is an alternative to {approve} that can be used as a mitigation for
                   * problems described in {IERC20-approve}.
                   *
                   * Emits an {Approval} event indicating the updated allowance.
                   *
                   * Requirements:
                   *
                   * - `spender` cannot be the zero address.
                   * - `spender` must have allowance for the caller of at least
                   * `subtractedValue`.
                   */
                  function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
                      _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
                      return true;
                  }
                  /**
                   * @dev Moves tokens `amount` from `sender` to `recipient`.
                   *
                   * This is internal function is equivalent to {transfer}, and can be used to
                   * e.g. implement automatic token fees, slashing mechanisms, etc.
                   *
                   * Emits a {Transfer} event.
                   *
                   * Requirements:
                   *
                   * - `sender` cannot be the zero address.
                   * - `recipient` cannot be the zero address.
                   * - `sender` must have a balance of at least `amount`.
                   */
                  function _transfer(address sender, address recipient, uint256 amount) internal virtual {
                      require(sender != address(0), "ERC20: transfer from the zero address");
                      require(recipient != address(0), "ERC20: transfer to the zero address");
                      _beforeTokenTransfer(sender, recipient, amount);
                      _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
                      _balances[recipient] = _balances[recipient].add(amount);
                      emit Transfer(sender, recipient, amount);
                  }
                  /** @dev Creates `amount` tokens and assigns them to `account`, increasing
                   * the total supply.
                   *
                   * Emits a {Transfer} event with `from` set to the zero address.
                   *
                   * Requirements:
                   *
                   * - `to` cannot be the zero address.
                   */
                  function _mint(address account, uint256 amount) internal virtual {
                      require(account != address(0), "ERC20: mint to the zero address");
                      _beforeTokenTransfer(address(0), account, amount);
                      _totalSupply = _totalSupply.add(amount);
                      _balances[account] = _balances[account].add(amount);
                      emit Transfer(address(0), account, amount);
                  }
                  /**
                   * @dev Destroys `amount` tokens from `account`, reducing the
                   * total supply.
                   *
                   * Emits a {Transfer} event with `to` set to the zero address.
                   *
                   * Requirements:
                   *
                   * - `account` cannot be the zero address.
                   * - `account` must have at least `amount` tokens.
                   */
                  function _burn(address account, uint256 amount) internal virtual {
                      require(account != address(0), "ERC20: burn from the zero address");
                      _beforeTokenTransfer(account, address(0), amount);
                      _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
                      _totalSupply = _totalSupply.sub(amount);
                      emit Transfer(account, address(0), amount);
                  }
                  /**
                   * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
                   *
                   * This internal function is equivalent to `approve`, and can be used to
                   * e.g. set automatic allowances for certain subsystems, etc.
                   *
                   * Emits an {Approval} event.
                   *
                   * Requirements:
                   *
                   * - `owner` cannot be the zero address.
                   * - `spender` cannot be the zero address.
                   */
                  function _approve(address owner, address spender, uint256 amount) internal virtual {
                      require(owner != address(0), "ERC20: approve from the zero address");
                      require(spender != address(0), "ERC20: approve to the zero address");
                      _allowances[owner][spender] = amount;
                      emit Approval(owner, spender, amount);
                  }
                  /**
                   * @dev Sets {decimals} to a value other than the default one of 18.
                   *
                   * WARNING: This function should only be called from the constructor. Most
                   * applications that interact with token contracts will not expect
                   * {decimals} to ever change, and may work incorrectly if it does.
                   */
                  function _setupDecimals(uint8 decimals_) internal virtual {
                      _decimals = decimals_;
                  }
                  /**
                   * @dev Hook that is called before any transfer of tokens. This includes
                   * minting and burning.
                   *
                   * Calling conditions:
                   *
                   * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
                   * will be to transferred to `to`.
                   * - when `from` is zero, `amount` tokens will be minted for `to`.
                   * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
                   * - `from` and `to` are never both zero.
                   *
                   * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
                   */
                  function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
              }
              // SPDX-License-Identifier: MIT
              pragma solidity >=0.6.0 <0.8.0;
              import "../../utils/Context.sol";
              import "./ERC20.sol";
              /**
               * @dev Extension of {ERC20} that allows token holders to destroy both their own
               * tokens and those that they have an allowance for, in a way that can be
               * recognized off-chain (via event analysis).
               */
              abstract contract ERC20Burnable is Context, ERC20 {
                  using SafeMath for uint256;
                  /**
                   * @dev Destroys `amount` tokens from the caller.
                   *
                   * See {ERC20-_burn}.
                   */
                  function burn(uint256 amount) public virtual {
                      _burn(_msgSender(), amount);
                  }
                  /**
                   * @dev Destroys `amount` tokens from `account`, deducting from the caller's
                   * allowance.
                   *
                   * See {ERC20-_burn} and {ERC20-allowance}.
                   *
                   * Requirements:
                   *
                   * - the caller must have allowance for ``accounts``'s tokens of at least
                   * `amount`.
                   */
                  function burnFrom(address account, uint256 amount) public virtual {
                      uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");
                      _approve(account, _msgSender(), decreasedAllowance);
                      _burn(account, amount);
                  }
              }
              // 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);
              }
              // SPDX-License-Identifier: MIT
              pragma solidity >=0.6.0 <0.8.0;
              /*
               * @dev Provides information about the current execution context, including the
               * sender of the transaction and its data. While these are generally available
               * via msg.sender and msg.data, they should not be accessed in such a direct
               * manner, since when dealing with GSN meta-transactions the account sending and
               * paying for execution may not be the actual sender (as far as an application
               * is concerned).
               *
               * This contract is only required for intermediate, library-like contracts.
               */
              abstract contract Context {
                  function _msgSender() internal view virtual returns (address payable) {
                      return msg.sender;
                  }
                  function _msgData() internal view virtual returns (bytes memory) {
                      this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                      return msg.data;
                  }
              }
              /**
                *       .
                *      / \\
                *     |.'.|
                *     |'.'|
                *   ,'|   |`.
                *  |,-'-|-'-.|
                *   __|_| |         _        _      _____           _
                *  | ___ \\|        | |      | |    | ___ \\         | |
                *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                * +---------------------------------------------------+
                * |    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/token/RocketTokenRPLInterface.sol";
              import "../../interface/rewards/RocketRewardsPoolInterface.sol";
              import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsRewardsInterface.sol";
              import "../../interface/RocketVaultInterface.sol";
              import "@openzeppelin/contracts/math/SafeMath.sol";
              // Holds RPL generated by the network for claiming from stakers (node operators etc)
              contract RocketRewardsPool is RocketBase, RocketRewardsPoolInterface {
                  // Libs
                  using SafeMath for uint;
                  // Events
                  event RPLTokensClaimed(address indexed claimingContract, address indexed claimingAddress, uint256 amount, uint256 time);  
                  
                  // Modifiers
                  /**
                  * @dev Throws if called by any sender that doesn't match a Rocket Pool claim contract
                  */
                  modifier onlyClaimContract() {
                      require(getClaimingContractExists(getContractName(msg.sender)), "Not a valid rewards claiming contact");
                      _;
                  }
                  /**
                  * @dev Throws if called by any sender that doesn't match an enabled Rocket Pool claim contract
                  */
                  modifier onlyEnabledClaimContract() {
                      require(getClaimingContractEnabled(getContractName(msg.sender)), "Not a valid rewards claiming contact or it has been disabled");
                      _;
                  }
                  // Construct
                  constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
                      // Version
                      version = 1;
                      // Set the claim interval start time as the current time
                      setUint(keccak256("rewards.pool.claim.interval.time.start"), block.timestamp);
                  }
                  /**
                  * Get how much RPL the Rewards Pool contract currently has assigned to it as a whole
                  * @return uint256 Returns rpl balance of rocket rewards contract
                  */
                  function getRPLBalance() override external view returns(uint256) {
                      // Get the vault contract instance
                      RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
                      // Check per contract
                      return rocketVault.balanceOfToken("rocketRewardsPool", IERC20(getContractAddress("rocketTokenRPL")));
                  }
                  /**
                  * Get the last set interval start time
                  * @return uint256 Last set start timestamp for a claim interval
                  */
                  function getClaimIntervalTimeStart() override public view returns(uint256) {
                      return getUint(keccak256("rewards.pool.claim.interval.time.start"));
                  }
                  /**
                  * Compute the current start time before a claim is made, takes into account intervals that may have passed
                  * @return uint256 Computed starting timestamp for next possible claim
                  */
                  function getClaimIntervalTimeStartComputed() override public view returns(uint256) {
                      // If intervals have passed, a new start timestamp will be used for the next claim, if it's the same interval then return that
                      uint256 claimIntervalTimeStart = getClaimIntervalTimeStart();
                      uint256 claimIntervalTime = getClaimIntervalTime();
                      return _getClaimIntervalTimeStartComputed(claimIntervalTimeStart, claimIntervalTime);
                  }
                  function _getClaimIntervalTimeStartComputed(uint256 _claimIntervalTimeStart, uint256 _claimIntervalTime) private view returns (uint256) {
                      uint256 claimIntervalsPassed = _getClaimIntervalsPassed(_claimIntervalTimeStart, _claimIntervalTime);
                      return claimIntervalsPassed == 0 ? _claimIntervalTimeStart : _claimIntervalTimeStart.add(_claimIntervalTime.mul(claimIntervalsPassed));
                  }
                  /**
                  * Compute intervals since last claim period
                  * @return uint256 Time intervals since last update
                  */
                  function getClaimIntervalsPassed() override public view returns(uint256) {
                      // Calculate now if inflation has begun
                      return _getClaimIntervalsPassed(getClaimIntervalTimeStart(), getClaimIntervalTime());
                  }
                  function _getClaimIntervalsPassed(uint256 _claimIntervalTimeStart, uint256 _claimIntervalTime) private view returns (uint256) {
                      return block.timestamp.sub(_claimIntervalTimeStart).div(_claimIntervalTime);
                  }
                  /**
                  * Get how many seconds in a claim interval
                  * @return uint256 Number of seconds in a claim interval
                  */
                  function getClaimIntervalTime() override public view returns(uint256) {
                      // Get from the DAO settings
                      RocketDAOProtocolSettingsRewardsInterface daoSettingsRewards = RocketDAOProtocolSettingsRewardsInterface(getContractAddress("rocketDAOProtocolSettingsRewards"));
                      return daoSettingsRewards.getRewardsClaimIntervalTime();
                  }
                  /**
                  * Get the last time a claim was made
                  * @return uint256 Last time a claim was made
                  */
                  function getClaimTimeLastMade() override external view returns(uint256) {
                      return getUint(keccak256("rewards.pool.claim.interval.time.last"));
                  }
                  // Check whether a claiming contract exists
                  function getClaimingContractExists(string memory _contractName) override public view returns (bool) {
                      RocketDAOProtocolSettingsRewardsInterface daoSettingsRewards = RocketDAOProtocolSettingsRewardsInterface(getContractAddress("rocketDAOProtocolSettingsRewards"));
                      return (daoSettingsRewards.getRewardsClaimerPercTimeUpdated(_contractName) > 0);
                  }
                  // If the claiming contact has a % allocated to it higher than 0, it can claim
                  function getClaimingContractEnabled(string memory _contractName) override public view returns (bool) {
                      // Load contract
                      RocketDAOProtocolSettingsRewardsInterface daoSettingsRewards = RocketDAOProtocolSettingsRewardsInterface(getContractAddress("rocketDAOProtocolSettingsRewards"));
                      // Now verify this contract can claim by having a claim perc > 0 
                      return daoSettingsRewards.getRewardsClaimerPerc(_contractName) > 0 ? true : false;
                  }
                  
                  /**
                  * The current claim amount total for this interval per claiming contract
                  * @return uint256 The current claim amount for this interval for the claiming contract
                  */
                  function getClaimingContractTotalClaimed(string memory _claimingContract) override external view returns(uint256) {
                      return _getClaimingContractTotalClaimed(_claimingContract, getClaimIntervalTimeStartComputed());
                  }
                  function _getClaimingContractTotalClaimed(string memory _claimingContract, uint256 _claimIntervalTimeStartComputed) private view returns(uint256) {
                      return getUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.contract.total", _claimIntervalTimeStartComputed, _claimingContract)));
                  }
                  
                  /**
                  * Have they claimed already during this interval? 
                  * @return bool Returns true if they can claim during this interval
                  */
                  function getClaimingContractUserHasClaimed(uint256 _claimIntervalStartTime, string memory _claimingContract, address _claimerAddress) override public view returns(bool) {
                      // Check per contract
                      return getBool(keccak256(abi.encodePacked("rewards.pool.claim.interval.claimer.address", _claimIntervalStartTime, _claimingContract, _claimerAddress)));
                  }
                  /**
                  * Get the time this account registered as a claimer at
                  * @return uint256 Returns the time the account was registered at
                  */
                  function getClaimingContractUserRegisteredTime(string memory _claimingContract, address _claimerAddress) override public view returns(uint256) {
                      return getUint(keccak256(abi.encodePacked("rewards.pool.claim.contract.registered.time", _claimingContract, _claimerAddress)));
                  }
                  
                  /**
                  * Get whether this address can currently make a claim
                  * @return bool Returns true if the _claimerAddress can make a claim
                  */
                  function getClaimingContractUserCanClaim(string memory _claimingContract, address _claimerAddress) override public view returns(bool) {
                      return _getClaimingContractUserCanClaim(_claimingContract, _claimerAddress, getClaimIntervalTime());
                  }
                  function _getClaimingContractUserCanClaim(string memory _claimingContract, address _claimerAddress, uint256 _claimIntervalTime) private view returns(bool) {
                      // Get the time they registered at
                      uint256 registeredTime = getClaimingContractUserRegisteredTime(_claimingContract, _claimerAddress);
                      // If it's 0 or hasn't passed one interval yet, they can't claim
                      return registeredTime > 0 && registeredTime.add(_claimIntervalTime) <= block.timestamp && getClaimingContractPerc(_claimingContract) > 0 ? true : false;
                  }
                  /**
                  * Get the number of claimers for the current interval per claiming contract
                  * @return uint256 Returns number of claimers for the current interval per claiming contract
                  */
                  function getClaimingContractUserTotalCurrent(string memory _claimingContract) override external view returns(uint256) {
                      // Return the current interval amount if in that interval, if we are moving to the next one upon next claim, use that
                      return getClaimIntervalsPassed() == 0 ? getUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.claimers.total.current", _claimingContract))) : getClaimingContractUserTotalNext(_claimingContract);
                  }
                  /**
                  * Get the number of claimers that will be added/removed on the next interval
                  * @return uint256 Returns the number of claimers that will be added/removed on the next interval
                  */
                  function getClaimingContractUserTotalNext(string memory _claimingContract) override public view returns(uint256) {
                      return getUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.claimers.total.next", _claimingContract)));
                  }
                  /**
                  * Get contract claiming percentage last recorded
                  * @return uint256 Returns the contract claiming percentage last recorded
                  */
                  function getClaimingContractPercLast(string memory _claimingContract) override public view returns(uint256) {
                      return getUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.contract.perc.current", _claimingContract)));
                  }
                 
                  /**
                  * Get the approx amount of rewards available for this claim interval
                  * @return uint256 Rewards amount for current claim interval
                  */
                  function getClaimIntervalRewardsTotal() override public view returns(uint256) {
                      // Get the RPL contract instance
                      RocketTokenRPLInterface rplContract = RocketTokenRPLInterface(getContractAddress("rocketTokenRPL"));
                      // Get the vault contract instance
                      RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
                      // Rewards amount
                      uint256 rewardsTotal = 0;
                      // Is this the first claim of this interval? If so, calculate expected inflation RPL + any RPL already in the pool
                      if(getClaimIntervalsPassed() > 0) {
                          // Get the balance of tokens that will be transferred to the vault for this contract when the first claim is made
                          // Also account for any RPL tokens already in the vault for the rewards pool
                          rewardsTotal = rplContract.inflationCalculate().add(rocketVault.balanceOfToken("rocketRewardsPool", IERC20(getContractAddress("rocketTokenRPL"))));
                      }else{
                          // Claims have already been made, lets retrieve rewards total stored on first claim of this interval
                          rewardsTotal = getUint(keccak256("rewards.pool.claim.interval.total"));
                      }
                      // Done
                      return rewardsTotal;
                  }
                  /**
                  * Get the percentage this contract can claim in this interval
                  * @return uint256 Rewards percentage this contract can claim in this interval
                  */
                  function getClaimingContractPerc(string memory _claimingContract) override public view returns(uint256) {
                      // Load contract
                      RocketDAOProtocolSettingsRewardsInterface daoSettingsRewards = RocketDAOProtocolSettingsRewardsInterface(getContractAddress("rocketDAOProtocolSettingsRewards"));
                      // Get the % amount allocated to this claim contract
                      uint256 claimContractPerc = daoSettingsRewards.getRewardsClaimerPerc(_claimingContract);
                      // Get the time the % was changed at, it will only use this % on the next interval
                      if(daoSettingsRewards.getRewardsClaimerPercTimeUpdated(_claimingContract) > getClaimIntervalTimeStartComputed()) {
                          // Ok so this percentage was set during this interval, we must use the current % assigned to the last claim and the new one will kick in the next interval
                          // If this is 0, the contract hasn't made a claim yet and can only do so on the next interval
                          claimContractPerc = getClaimingContractPercLast(_claimingContract);
                      }
                      // Done
                      return claimContractPerc;
                  }
                  /**
                  * Get the approx amount of rewards available for this claim interval per claiming contract
                  * @return uint256 Rewards amount for current claim interval per claiming contract
                  */
                  function getClaimingContractAllowance(string memory _claimingContract) override public view returns(uint256) {
                      // Get the % amount this claim contract will get
                      uint256 claimContractPerc = getClaimingContractPerc(_claimingContract);
                      // How much rewards are available for this claim interval?
                      uint256 claimIntervalRewardsTotal = getClaimIntervalRewardsTotal();
                      // How much this claiming contract is entitled to in perc
                      uint256 contractClaimTotal = 0;
                      // Check now
                      if(claimContractPerc > 0 && claimIntervalRewardsTotal > 0)  {
                          // Calculate how much rewards this claimer will receive based on their claiming perc
                          contractClaimTotal = claimContractPerc.mul(claimIntervalRewardsTotal).div(calcBase);
                      }
                      // Done
                      return contractClaimTotal;
                  }
                  
                  // How much this claimer is entitled to claim, checks parameters that claim() will check
                  function getClaimAmount(string memory _claimingContract, address _claimerAddress, uint256 _claimerAmountPerc) override external view returns (uint256) {
                      if (!getClaimingContractUserCanClaim(_claimingContract, _claimerAddress)) {
                          return 0;
                      }
                      uint256 claimIntervalTimeStartComptued = getClaimIntervalTimeStartComputed();
                      uint256 claimingContractTotalClaimed = _getClaimingContractTotalClaimed(_claimingContract, claimIntervalTimeStartComptued);
                      return _getClaimAmount(_claimingContract, _claimerAddress, _claimerAmountPerc, claimIntervalTimeStartComptued, claimingContractTotalClaimed);
                  }
                  function _getClaimAmount(string memory _claimingContract, address _claimerAddress, uint256 _claimerAmountPerc, uint256 _claimIntervalTimeStartComputed, uint256 _claimingContractTotalClaimed) private view returns (uint256) {
                      // Get the total rewards available for this claiming contract
                      uint256 contractClaimTotal = getClaimingContractAllowance(_claimingContract);
                      // How much of the above that this claimer will receive
                      uint256 claimerTotal = 0;
                      // Are we good to proceed?
                      if( contractClaimTotal > 0 &&
                          _claimerAmountPerc > 0 &&
                          _claimerAmountPerc <= 1 ether &&
                          _claimerAddress != address(0x0) &&
                          getClaimingContractEnabled(_claimingContract) &&
                          !getClaimingContractUserHasClaimed(_claimIntervalTimeStartComputed, _claimingContract, _claimerAddress)) {
                          // Now calculate how much this claimer would receive
                          claimerTotal = _claimerAmountPerc.mul(contractClaimTotal).div(calcBase);
                          // Is it more than currently available + the amount claimed already for this claim interval?
                          claimerTotal = claimerTotal.add(_claimingContractTotalClaimed) <= contractClaimTotal ? claimerTotal : 0;
                      }
                      // Done
                      return claimerTotal;
                  }
                  // An account must be registered to claim from the rewards pool. They must wait one claim interval before they can collect.
                  // Also keeps track of total 
                  function registerClaimer(address _claimerAddress, bool _enabled) override external onlyClaimContract { 
                      // The name of the claiming contract
                      string memory contractName = getContractName(msg.sender);
                      // Record the time they are registering at
                      uint256 registeredTime = 0;
                      // How many users are to be included in next interval
                      uint256 claimersIntervalTotalUpdate = getClaimingContractUserTotalNext(contractName);
                      // Ok register
                      if(_enabled) { 
                          // Make sure they are not already registered
                          require(getClaimingContractUserRegisteredTime(contractName, _claimerAddress) == 0, "Claimer is already registered");
                          // Update time
                          registeredTime = block.timestamp;
                          // Update the total registered claimers for next interval
                          setUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.claimers.total.next", contractName)), claimersIntervalTotalUpdate.add(1));
                      }else{
                          // Make sure they are already registered
                          require(getClaimingContractUserRegisteredTime(contractName, _claimerAddress) != 0, "Claimer is not registered");
                          // Update the total registered claimers for next interval
                          setUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.claimers.total.next", contractName)), claimersIntervalTotalUpdate.sub(1));
                      }
                      // Save the registered time
                      setUint(keccak256(abi.encodePacked("rewards.pool.claim.contract.registered.time", contractName, _claimerAddress)), registeredTime);
                  }
                  // A claiming contract claiming for a user and the percentage of the rewards they are allowed to receive
                  function claim(address _claimerAddress, address _toAddress, uint256 _claimerAmountPerc) override external onlyEnabledClaimContract {
                      // The name of the claiming contract
                      string memory contractName = getContractName(msg.sender);
                      // Check to see if this registered claimer has waited one interval before collecting
                      uint256 claimIntervalTime = getClaimIntervalTime();
                      require(_getClaimingContractUserCanClaim(contractName, _claimerAddress, claimIntervalTime), "Registered claimer is not registered to claim or has not waited one claim interval");
                      // RPL contract address
                      address rplContractAddress = getContractAddress("rocketTokenRPL");
                      // RPL contract instance
                      RocketTokenRPLInterface rplContract = RocketTokenRPLInterface(rplContractAddress);
                      // Get the vault contract instance
                      RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
                      // Get the start of the last claim interval as this may have just changed for a new interval beginning
                      uint256 claimIntervalTimeStart = getClaimIntervalTimeStart();
                      uint256 claimIntervalTimeStartComputed = _getClaimIntervalTimeStartComputed(claimIntervalTimeStart, claimIntervalTime);
                      uint256 claimIntervalsPassed = _getClaimIntervalsPassed(claimIntervalTimeStart, claimIntervalTime);
                      // Is this the first claim of this interval? If so, set the rewards total for this interval
                      if (claimIntervalsPassed > 0) {
                          // Mint any new tokens from the RPL inflation
                          rplContract.inflationMintTokens();
                          // Get how many tokens are in the reward pool to be available for this claim period
                          setUint(keccak256("rewards.pool.claim.interval.total"), rocketVault.balanceOfToken("rocketRewardsPool", rplContract));
                          // Set this as the start of the new claim interval
                          setUint(keccak256("rewards.pool.claim.interval.time.start"), claimIntervalTimeStartComputed);
                          // Soon as we mint new tokens, send the DAO's share to it's claiming contract, then attempt to transfer them to the dao if possible
                          uint256 daoClaimContractAllowance = getClaimingContractAllowance("rocketClaimDAO");
                          // Are we sending any?
                          if (daoClaimContractAllowance > 0) {
                              // Get the DAO claim contract address
                              address daoClaimContractAddress = getContractAddress("rocketClaimDAO");
                              // Transfers the DAO's tokens to it's claiming contract from the rewards pool
                              rocketVault.transferToken("rocketClaimDAO", rplContract, daoClaimContractAllowance);
                              // Set the current claim percentage this contract is entitled to for this interval
                              setUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.contract.perc.current", "rocketClaimDAO")), getClaimingContractPerc("rocketClaimDAO"));
                              // Store the total RPL rewards claim for this claiming contract in this interval
                              setUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.contract.total", claimIntervalTimeStartComputed, "rocketClaimDAO")), _getClaimingContractTotalClaimed("rocketClaimDAO", claimIntervalTimeStartComputed).add(daoClaimContractAllowance));
                              // Log it
                              emit RPLTokensClaimed(daoClaimContractAddress, daoClaimContractAddress, daoClaimContractAllowance, block.timestamp);
                          }
                      }
                      // Has anyone claimed from this contract so far in this interval? If not then set the interval settings for the contract
                      if (_getClaimingContractTotalClaimed(contractName, claimIntervalTimeStartComputed) == 0) {
                          // Get the amount allocated to this claim contract
                          uint256 claimContractAllowance = getClaimingContractAllowance(contractName);
                          // Make sure this is ok
                          require(claimContractAllowance > 0, "Claiming contract must have an allowance of more than 0");
                          // Set the current claim percentage this contract is entitled too for this interval
                          setUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.contract.perc.current", contractName)), getClaimingContractPerc(contractName));
                          // Set the current claim allowance amount for this contract for this claim interval (if the claim amount is changed, it will kick in on the next interval)
                          setUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.contract.allowance", contractName)), claimContractAllowance);
                          // Set the current amount of claimers for this interval
                          setUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.claimers.total.current", contractName)), getClaimingContractUserTotalNext(contractName));
                      }
                      // Check if they have a valid claim amount
                      uint256 claimingContractTotalClaimed = _getClaimingContractTotalClaimed(contractName, claimIntervalTimeStartComputed);
                      uint256 claimAmount = _getClaimAmount(contractName, _claimerAddress, _claimerAmountPerc, claimIntervalTimeStartComputed, claimingContractTotalClaimed);
                      // First initial checks
                      require(claimAmount > 0, "Claimer is not entitled to tokens, they have already claimed in this interval or they are claiming more rewards than available to this claiming contract.");
                      // Send tokens now
                      rocketVault.withdrawToken(_toAddress, rplContract, claimAmount);
                      // Store the claiming record for this interval and claiming contract
                      setBool(keccak256(abi.encodePacked("rewards.pool.claim.interval.claimer.address", claimIntervalTimeStartComputed, contractName, _claimerAddress)), true);
                      // Store the total RPL rewards claim for this claiming contract in this interval
                      setUint(keccak256(abi.encodePacked("rewards.pool.claim.interval.contract.total", claimIntervalTimeStartComputed, contractName)), claimingContractTotalClaimed.add(claimAmount));
                      // Store the last time a claim was made
                      setUint(keccak256("rewards.pool.claim.interval.time.last"), block.timestamp);
                      // Log it
                      emit RPLTokensClaimed(getContractAddress(contractName), _claimerAddress, claimAmount, block.timestamp);
                  }
              }
              /**
                *       .
                *      / \\
                *     |.'.|
                *     |'.'|
                *   ,'|   |`.
                *  |,-'-|-'-.|
                *   __|_| |         _        _      _____           _
                *  | ___ \\|        | |      | |    | ___ \\         | |
                *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                * +---------------------------------------------------+
                * |    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
              import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
              import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
              interface RocketVaultInterface {
                  function balanceOf(string memory _networkContractName) external view returns (uint256);
                  function depositEther() external payable;
                  function withdrawEther(uint256 _amount) external;
                  function depositToken(string memory _networkContractName, IERC20 _tokenAddress, uint256 _amount) external;
                  function withdrawToken(address _withdrawalAddress, IERC20 _tokenAddress, uint256 _amount) external;
                  function balanceOfToken(string memory _networkContractName, IERC20 _tokenAddress) external view returns (uint256);
                  function transferToken(string memory _networkContractName, IERC20 _tokenAddress, uint256 _amount) external;
                  function burnToken(ERC20Burnable _tokenAddress, uint256 _amount) 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 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    |
                * +---------------------------------------------------+
                *
                *  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 RocketRewardsPoolInterface {
                  function getRPLBalance() external view returns(uint256);
                  function getClaimIntervalTimeStart() external view returns(uint256);
                  function getClaimIntervalTimeStartComputed() external view returns(uint256);
                  function getClaimIntervalsPassed() external view returns(uint256);
                  function getClaimIntervalTime() external view returns(uint256);
                  function getClaimTimeLastMade() external view returns(uint256);
                  function getClaimIntervalRewardsTotal() external view returns(uint256);
                  function getClaimingContractTotalClaimed(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractUserTotalNext(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractUserTotalCurrent(string memory _claimingContract) external view returns(uint256);  
                  function getClaimingContractUserHasClaimed(uint256 _claimIntervalStartTime, string memory _claimingContract, address _claimerAddress) external view returns(bool);
                  function getClaimingContractUserCanClaim(string memory _claimingContract, address _claimerAddress) external view returns(bool);
                  function getClaimingContractUserRegisteredTime(string memory _claimingContract, address _claimerAddress) external view returns(uint256);
                  function getClaimingContractAllowance(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractPerc(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractPercLast(string memory _claimingContract) external view returns(uint256);
                  function getClaimingContractExists(string memory _contractName) external view returns (bool);
                  function getClaimingContractEnabled(string memory _contractName) external view returns (bool);
                  function getClaimAmount(string memory _claimingContract, address _claimerAddress, uint256 _claimerAmountPerc) external view returns (uint256);
                  function registerClaimer(address _claimerAddress, bool _enabled) external;
                  function claim(address _claimerAddress, address _toAddress, uint256 _claimerAmount) 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
              import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
              interface RocketTokenRPLInterface is IERC20 {
                  function getInflationCalcTime() external view returns(uint256);
                  function getInflationIntervalTime() external view returns(uint256);
                  function getInflationIntervalRate() external view returns(uint256);
                  function getInflationIntervalsPassed() external view returns(uint256);
                  function getInflationIntervalStartTime() external view returns(uint256);
                  function getInflationRewardsContractAddress() external view returns(address);
                  function inflationCalculate() external view returns (uint256);
                  function inflationMintTokens() external returns (uint256);
                  function swapTokens(uint256 _amount) external;
              }
              

              File 7 of 7: RocketDAOProtocolSettingsRewards
              // 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/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    |
                * +---------------------------------------------------+
                *
                *  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 "./RocketDAOProtocolSettings.sol";
              import "../../../../interface/dao/protocol/settings/RocketDAOProtocolSettingsRewardsInterface.sol";
              import "@openzeppelin/contracts/math/SafeMath.sol";
              // Settings in RP which the DAO will have full control over
              contract RocketDAOProtocolSettingsRewards is RocketDAOProtocolSettings, RocketDAOProtocolSettingsRewardsInterface {
                  using SafeMath for uint;
                  // Construct
                  constructor(RocketStorageInterface _rocketStorageAddress) RocketDAOProtocolSettings(_rocketStorageAddress, "rewards") {
                      // Set version 
                      version = 1;
                       // Set some initial settings on first deployment
                      if(!getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")))) {
                          // Each of the initial RPL reward claiming contracts
                          setSettingRewardsClaimer('rocketClaimDAO', 0.1 ether);                                              // DAO Rewards claim % amount - Percentage given of 1 ether
                          setSettingRewardsClaimer('rocketClaimNode', 0.70 ether);                                            // Bonded Node Rewards claim % amount - Percentage given of 1 ether
                          setSettingRewardsClaimer('rocketClaimTrustedNode', 0.2 ether);                                      // Trusted Node Rewards claim % amount - Percentage given of 1 ether
                          // RPL Claims settings
                          setSettingUint("rpl.rewards.claim.period.time", 28 days);                                           // The time in which a claim period will span in seconds - 28 days by default
                          // Deployment check
                          setBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")), true);                           // Flag that this contract has been deployed, so default settings don't get reapplied on a contract upgrade
                      }
                  }
                  /*** Settings ****************/
                  // Set a new claimer for the rpl rewards, must specify a unique contract name that will be claiming from and a percentage of the rewards
                  function setSettingRewardsClaimer(string memory _contractName, uint256 _perc) override public onlyDAOProtocolProposal {
                      // Get the total perc set, can't be more than 100
                      uint256 percTotal = getRewardsClaimersPercTotal();
                      // If this group already exists, it will update the perc
                      uint256 percTotalUpdate = percTotal.add(_perc).sub(getRewardsClaimerPerc(_contractName));
                      // Can't be more than a total claim amount of 100%
                      require(percTotalUpdate <= 1 ether, "Claimers cannot total more than 100%");
                      // Update the total
                      setUint(keccak256(abi.encodePacked(settingNameSpace,"rewards.claims", "group.totalPerc")), percTotalUpdate);
                      // Update/Add the claimer amount
                      setUint(keccak256(abi.encodePacked(settingNameSpace, "rewards.claims", "group.amount", _contractName)), _perc);
                      // Set the time it was updated at
                      setUint(keccak256(abi.encodePacked(settingNameSpace, "rewards.claims", "group.amount.updated.time", _contractName)), block.timestamp);
                  }
                  /*** RPL Claims ***********************************************/
                  // RPL Rewards Claimers (own namespace to prevent DAO setting voting to overwrite them)
                  // Get the perc amount that this rewards contract get claim
                  function getRewardsClaimerPerc(string memory _contractName) override public view returns (uint256) {
                      return getUint(keccak256(abi.encodePacked(settingNameSpace, "rewards.claims", "group.amount", _contractName)));
                  } 
                  // Get the time of when the claim perc was last updated
                  function getRewardsClaimerPercTimeUpdated(string memory _contractName) override external view returns (uint256) {
                      return getUint(keccak256(abi.encodePacked(settingNameSpace, "rewards.claims", "group.amount.updated.time", _contractName)));
                  } 
                  // Get the perc amount total for all claimers (remaining goes to DAO)
                  function getRewardsClaimersPercTotal() override public view returns (uint256) {
                      return getUint(keccak256(abi.encodePacked(settingNameSpace, "rewards.claims", "group.totalPerc")));
                  }
                  // RPL Rewards General Settings
                  // The period over which claims can be made
                  function getRewardsClaimIntervalTime() override external view returns (uint256) {
                      return getSettingUint("rpl.rewards.claim.period.time");
                  }
              }
              /**
                *       .
                *      / \\
                *     |.'.|
                *     |'.'|
                *   ,'|   |`.
                *  |,-'-|-'-.|
                *   __|_| |         _        _      _____           _
                *  | ___ \\|        | |      | |    | ___ \\         | |
                *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                * +---------------------------------------------------+
                * |    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 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    |
                * +---------------------------------------------------+
                *
                *  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 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);
              }