ETH Price: $2,280.33 (-6.41%)

Transaction Decoder

Block:
21212799 at Nov-18-2024 06:25:59 AM +UTC
Transaction Fee:
0.000459093895515216 ETH $1.05
Gas Used:
39,026 Gas / 11.763795816 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x11d5F452...Cb04b5268
(Rocket Pool: Eth2 Depositor 1216)
0.084155415414593427 Eth
Nonce: 244
0.083696321519078211 Eth
Nonce: 245
0.000459093895515216
0x7300Ed20...4f03674fb
(beaverbuild)
19.542814611914745136 Eth19.542873150914745136 Eth0.000058539

Execution Trace

RocketMinipoolBase.setUseLatestDelegate( _setting=True )
  • RocketMinipoolBase.setUseLatestDelegate( _setting=True )
    • RocketStorage.getNodeWithdrawalAddress( _nodeAddress=0x11d5F45239a2833a0a95596B1317A36Cb04b5268 ) => ( 0x83A82BF1B555798CD1C7f3C51a7C91c548cBb401 )
      File 1 of 3: RocketMinipoolBase
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity >0.5.0 <0.9.0;
      // SPDX-License-Identifier: GPL-3.0-only
      interface RocketStorageInterface {
          // Deploy status
          function getDeployedStatus() external view returns (bool);
          // Guardian
          function getGuardian() external view returns(address);
          function setGuardian(address _newAddress) external;
          function confirmGuardian() external;
          // Getters
          function getAddress(bytes32 _key) external view returns (address);
          function getUint(bytes32 _key) external view returns (uint);
          function getString(bytes32 _key) external view returns (string memory);
          function getBytes(bytes32 _key) external view returns (bytes memory);
          function getBool(bytes32 _key) external view returns (bool);
          function getInt(bytes32 _key) external view returns (int);
          function getBytes32(bytes32 _key) external view returns (bytes32);
          // Setters
          function setAddress(bytes32 _key, address _value) external;
          function setUint(bytes32 _key, uint _value) external;
          function setString(bytes32 _key, string calldata _value) external;
          function setBytes(bytes32 _key, bytes calldata _value) external;
          function setBool(bytes32 _key, bool _value) external;
          function setInt(bytes32 _key, int _value) external;
          function setBytes32(bytes32 _key, bytes32 _value) external;
          // Deleters
          function deleteAddress(bytes32 _key) external;
          function deleteUint(bytes32 _key) external;
          function deleteString(bytes32 _key) external;
          function deleteBytes(bytes32 _key) external;
          function deleteBool(bytes32 _key) external;
          function deleteInt(bytes32 _key) external;
          function deleteBytes32(bytes32 _key) external;
          // Arithmetic
          function addUint(bytes32 _key, uint256 _amount) external;
          function subUint(bytes32 _key, uint256 _amount) external;
          // Protected storage
          function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
          function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
          function setWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress, bool _confirm) external;
          function confirmWithdrawalAddress(address _nodeAddress) external;
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity 0.7.6;
      // SPDX-License-Identifier: GPL-3.0-only
      // Represents the type of deposits required by a minipool
      enum MinipoolDeposit {
          None,       // Marks an invalid deposit type
          Full,       // The minipool requires 32 ETH from the node operator, 16 ETH of which will be refinanced from user deposits
          Half,       // The minipool required 16 ETH from the node operator to be matched with 16 ETH from user deposits
          Empty,      // The minipool requires 0 ETH from the node operator to be matched with 32 ETH from user deposits (trusted nodes only)
          Variable    // Indicates this minipool is of the new generation that supports a variable deposit amount
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity 0.7.6;
      // SPDX-License-Identifier: GPL-3.0-only
      // Represents a minipool's status within the network
      enum MinipoolStatus {
          Initialised,    // The minipool has been initialised and is awaiting a deposit of user ETH
          Prelaunch,      // The minipool has enough ETH to begin staking and is awaiting launch by the node operator
          Staking,        // The minipool is currently staking
          Withdrawable,   // NO LONGER USED
          Dissolved       // The minipool has been dissolved and its user deposited ETH has been returned to the deposit pool
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity 0.7.6;
      // SPDX-License-Identifier: GPL-3.0-only
      import "../../interface/RocketStorageInterface.sol";
      import "../../types/MinipoolDeposit.sol";
      import "../../types/MinipoolStatus.sol";
      // The RocketMinipool contract storage layout, shared by RocketMinipoolDelegate
      // ******************************************************
      // Note: This contract MUST NOT BE UPDATED after launch.
      // All deployed minipool contracts must maintain a
      // Consistent storage layout with RocketMinipoolDelegate.
      // ******************************************************
      abstract contract RocketMinipoolStorageLayout {
          // Storage state enum
          enum StorageState {
              Undefined,
              Uninitialised,
              Initialised
          }
      \t// Main Rocket Pool storage contract
          RocketStorageInterface internal rocketStorage = RocketStorageInterface(0);
          // Status
          MinipoolStatus internal status;
          uint256 internal statusBlock;
          uint256 internal statusTime;
          uint256 internal withdrawalBlock;
          // Deposit type
          MinipoolDeposit internal depositType;
          // Node details
          address internal nodeAddress;
          uint256 internal nodeFee;
          uint256 internal nodeDepositBalance;
          bool internal nodeDepositAssigned;          // NO LONGER IN USE
          uint256 internal nodeRefundBalance;
          uint256 internal nodeSlashBalance;
          // User deposit details
          uint256 internal userDepositBalanceLegacy;
          uint256 internal userDepositAssignedTime;
          // Upgrade options
          bool internal useLatestDelegate = false;
          address internal rocketMinipoolDelegate;
          address internal rocketMinipoolDelegatePrev;
          // Local copy of RETH address
          address internal rocketTokenRETH;
          // Local copy of penalty contract
          address internal rocketMinipoolPenalty;
          // Used to prevent direct access to delegate and prevent calling initialise more than once
          StorageState internal storageState = StorageState.Undefined;
          // Whether node operator has finalised the pool
          bool internal finalised;
          // Trusted member scrub votes
          mapping(address => bool) internal memberScrubVotes;
          uint256 internal totalScrubVotes;
          // Variable minipool
          uint256 internal preLaunchValue;
          uint256 internal userDepositBalance;
          // Vacant minipool
          bool internal vacant;
          uint256 internal preMigrationBalance;
          // User distribution
          bool internal userDistributed;
          uint256 internal userDistributeTime;
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity >0.5.0 <0.9.0;
      // SPDX-License-Identifier: GPL-3.0-only
      interface RocketMinipoolBaseInterface {
          function initialise(address _rocketStorage, address _nodeAddress) external;
          function delegateUpgrade() external;
          function delegateRollback() external;
          function setUseLatestDelegate(bool _setting) external;
          function getUseLatestDelegate() external view returns (bool);
          function getDelegate() external view returns (address);
          function getPreviousDelegate() external view returns (address);
          function getEffectiveDelegate() external view returns (address);
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      // SPDX-License-Identifier: GPL-3.0-only
      pragma solidity 0.7.6;
      import "./RocketMinipoolStorageLayout.sol";
      import "../../interface/RocketStorageInterface.sol";
      import "../../interface/minipool/RocketMinipoolBaseInterface.sol";
      /// @notice Contains the initialisation and delegate upgrade logic for minipools
      contract RocketMinipoolBase is RocketMinipoolBaseInterface, RocketMinipoolStorageLayout {
          // Events
          event EtherReceived(address indexed from, uint256 amount, uint256 time);
          event DelegateUpgraded(address oldDelegate, address newDelegate, uint256 time);
          event DelegateRolledBack(address oldDelegate, address newDelegate, uint256 time);
          // Store a reference to the address of RocketMinipoolBase itself to prevent direct calls to this contract
          address immutable self;
          constructor () {
              self = address(this);
          }
          /// @dev Prevent direct calls to this contract
          modifier notSelf() {
              require(address(this) != self);
              _;
          }
          /// @dev Only allow access from the owning node address
          modifier onlyMinipoolOwner() {
              // Only the node operator can upgrade
              address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(nodeAddress);
              require(msg.sender == nodeAddress || msg.sender == withdrawalAddress, "Only the node operator can access this method");
              _;
          }
          /// @notice Sets up starting delegate contract and then delegates initialisation to it
          function initialise(address _rocketStorage, address _nodeAddress) external override notSelf {
              // Check input
              require(_nodeAddress != address(0), "Invalid node address");
              require(storageState == StorageState.Undefined, "Already initialised");
              // Set storage state to uninitialised
              storageState = StorageState.Uninitialised;
              // Set rocketStorage
              rocketStorage = RocketStorageInterface(_rocketStorage);
              // Set the current delegate
              address delegateAddress = getContractAddress("rocketMinipoolDelegate");
              rocketMinipoolDelegate = delegateAddress;
              // Check for contract existence
              require(contractExists(delegateAddress), "Delegate contract does not exist");
              // Call initialise on delegate
              (bool success, bytes memory data) = delegateAddress.delegatecall(abi.encodeWithSignature('initialise(address)', _nodeAddress));
              if (!success) { revert(getRevertMessage(data)); }
          }
          /// @notice Receive an ETH deposit
          receive() external payable notSelf {
              // Emit ether received event
              emit EtherReceived(msg.sender, msg.value, block.timestamp);
          }
          /// @notice Upgrade this minipool to the latest network delegate contract
          function delegateUpgrade() external override onlyMinipoolOwner notSelf {
              // Set previous address
              rocketMinipoolDelegatePrev = rocketMinipoolDelegate;
              // Set new delegate
              rocketMinipoolDelegate = getContractAddress("rocketMinipoolDelegate");
              // Verify
              require(rocketMinipoolDelegate != rocketMinipoolDelegatePrev, "New delegate is the same as the existing one");
              // Log event
              emit DelegateUpgraded(rocketMinipoolDelegatePrev, rocketMinipoolDelegate, block.timestamp);
          }
          /// @notice Rollback to previous delegate contract
          function delegateRollback() external override onlyMinipoolOwner notSelf {
              // Make sure they have upgraded before
              require(rocketMinipoolDelegatePrev != address(0x0), "Previous delegate contract is not set");
              // Store original
              address originalDelegate = rocketMinipoolDelegate;
              // Update delegate to previous and zero out previous
              rocketMinipoolDelegate = rocketMinipoolDelegatePrev;
              rocketMinipoolDelegatePrev = address(0x0);
              // Log event
              emit DelegateRolledBack(originalDelegate, rocketMinipoolDelegate, block.timestamp);
          }
          /// @notice Sets the flag to automatically use the latest delegate contract or not
          /// @param _setting If true, will always use the latest delegate contract
          function setUseLatestDelegate(bool _setting) external override onlyMinipoolOwner notSelf {
              useLatestDelegate = _setting;
          }
          /// @notice Returns true if this minipool always uses the latest delegate contract
          function getUseLatestDelegate() external override view returns (bool) {
              return useLatestDelegate;
          }
          /// @notice Returns the address of the minipool's stored delegate
          function getDelegate() external override view returns (address) {
              return rocketMinipoolDelegate;
          }
          /// @notice Returns the address of the minipool's previous delegate (or address(0) if not set)
          function getPreviousDelegate() external override view returns (address) {
              return rocketMinipoolDelegatePrev;
          }
          /// @notice Returns the delegate which will be used when calling this minipool taking into account useLatestDelegate setting
          function getEffectiveDelegate() external override view returns (address) {
              return useLatestDelegate ? getContractAddress("rocketMinipoolDelegate") : rocketMinipoolDelegate;
          }
          /// @notice Delegates all calls to minipool delegate contract (or latest if flag is set)
          fallback(bytes calldata _input) external payable notSelf returns (bytes memory) {
              // If useLatestDelegate is set, use the latest delegate contract
              address delegateContract = useLatestDelegate ? getContractAddress("rocketMinipoolDelegate") : rocketMinipoolDelegate;
              // Check for contract existence
              require(contractExists(delegateContract), "Delegate contract does not exist");
              // Execute delegatecall
              (bool success, bytes memory data) = delegateContract.delegatecall(_input);
              if (!success) { revert(getRevertMessage(data)); }
              return data;
          }
          /// @dev Get the address of a Rocket Pool network contract
          function getContractAddress(string memory _contractName) private view returns (address) {
              address contractAddress = rocketStorage.getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
              require(contractAddress != address(0x0), "Contract not found");
              return contractAddress;
          }
          /// @dev Get a revert message from delegatecall return data
          function getRevertMessage(bytes memory _returnData) private pure returns (string memory) {
              if (_returnData.length < 68) { return "Transaction reverted silently"; }
              assembly {
                  _returnData := add(_returnData, 0x04)
              }
              return abi.decode(_returnData, (string));
          }
          /// @dev Returns true if contract exists at _contractAddress (if called during that contract's construction it will return a false negative)
          function contractExists(address _contractAddress) private view returns (bool) {
              uint32 codeSize;
              assembly {
                  codeSize := extcodesize(_contractAddress)
              }
              return codeSize > 0;
          }
      }
      

      File 2 of 3: RocketMinipoolBase
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity >0.5.0 <0.9.0;
      // SPDX-License-Identifier: GPL-3.0-only
      interface RocketStorageInterface {
          // Deploy status
          function getDeployedStatus() external view returns (bool);
          // Guardian
          function getGuardian() external view returns(address);
          function setGuardian(address _newAddress) external;
          function confirmGuardian() external;
          // Getters
          function getAddress(bytes32 _key) external view returns (address);
          function getUint(bytes32 _key) external view returns (uint);
          function getString(bytes32 _key) external view returns (string memory);
          function getBytes(bytes32 _key) external view returns (bytes memory);
          function getBool(bytes32 _key) external view returns (bool);
          function getInt(bytes32 _key) external view returns (int);
          function getBytes32(bytes32 _key) external view returns (bytes32);
          // Setters
          function setAddress(bytes32 _key, address _value) external;
          function setUint(bytes32 _key, uint _value) external;
          function setString(bytes32 _key, string calldata _value) external;
          function setBytes(bytes32 _key, bytes calldata _value) external;
          function setBool(bytes32 _key, bool _value) external;
          function setInt(bytes32 _key, int _value) external;
          function setBytes32(bytes32 _key, bytes32 _value) external;
          // Deleters
          function deleteAddress(bytes32 _key) external;
          function deleteUint(bytes32 _key) external;
          function deleteString(bytes32 _key) external;
          function deleteBytes(bytes32 _key) external;
          function deleteBool(bytes32 _key) external;
          function deleteInt(bytes32 _key) external;
          function deleteBytes32(bytes32 _key) external;
          // Arithmetic
          function addUint(bytes32 _key, uint256 _amount) external;
          function subUint(bytes32 _key, uint256 _amount) external;
          // Protected storage
          function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
          function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
          function setWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress, bool _confirm) external;
          function confirmWithdrawalAddress(address _nodeAddress) external;
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity 0.7.6;
      // SPDX-License-Identifier: GPL-3.0-only
      // Represents the type of deposits required by a minipool
      enum MinipoolDeposit {
          None,       // Marks an invalid deposit type
          Full,       // The minipool requires 32 ETH from the node operator, 16 ETH of which will be refinanced from user deposits
          Half,       // The minipool required 16 ETH from the node operator to be matched with 16 ETH from user deposits
          Empty,      // The minipool requires 0 ETH from the node operator to be matched with 32 ETH from user deposits (trusted nodes only)
          Variable    // Indicates this minipool is of the new generation that supports a variable deposit amount
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity 0.7.6;
      // SPDX-License-Identifier: GPL-3.0-only
      // Represents a minipool's status within the network
      enum MinipoolStatus {
          Initialised,    // The minipool has been initialised and is awaiting a deposit of user ETH
          Prelaunch,      // The minipool has enough ETH to begin staking and is awaiting launch by the node operator
          Staking,        // The minipool is currently staking
          Withdrawable,   // NO LONGER USED
          Dissolved       // The minipool has been dissolved and its user deposited ETH has been returned to the deposit pool
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity 0.7.6;
      // SPDX-License-Identifier: GPL-3.0-only
      import "../../interface/RocketStorageInterface.sol";
      import "../../types/MinipoolDeposit.sol";
      import "../../types/MinipoolStatus.sol";
      // The RocketMinipool contract storage layout, shared by RocketMinipoolDelegate
      // ******************************************************
      // Note: This contract MUST NOT BE UPDATED after launch.
      // All deployed minipool contracts must maintain a
      // Consistent storage layout with RocketMinipoolDelegate.
      // ******************************************************
      abstract contract RocketMinipoolStorageLayout {
          // Storage state enum
          enum StorageState {
              Undefined,
              Uninitialised,
              Initialised
          }
      \t// Main Rocket Pool storage contract
          RocketStorageInterface internal rocketStorage = RocketStorageInterface(0);
          // Status
          MinipoolStatus internal status;
          uint256 internal statusBlock;
          uint256 internal statusTime;
          uint256 internal withdrawalBlock;
          // Deposit type
          MinipoolDeposit internal depositType;
          // Node details
          address internal nodeAddress;
          uint256 internal nodeFee;
          uint256 internal nodeDepositBalance;
          bool internal nodeDepositAssigned;          // NO LONGER IN USE
          uint256 internal nodeRefundBalance;
          uint256 internal nodeSlashBalance;
          // User deposit details
          uint256 internal userDepositBalanceLegacy;
          uint256 internal userDepositAssignedTime;
          // Upgrade options
          bool internal useLatestDelegate = false;
          address internal rocketMinipoolDelegate;
          address internal rocketMinipoolDelegatePrev;
          // Local copy of RETH address
          address internal rocketTokenRETH;
          // Local copy of penalty contract
          address internal rocketMinipoolPenalty;
          // Used to prevent direct access to delegate and prevent calling initialise more than once
          StorageState internal storageState = StorageState.Undefined;
          // Whether node operator has finalised the pool
          bool internal finalised;
          // Trusted member scrub votes
          mapping(address => bool) internal memberScrubVotes;
          uint256 internal totalScrubVotes;
          // Variable minipool
          uint256 internal preLaunchValue;
          uint256 internal userDepositBalance;
          // Vacant minipool
          bool internal vacant;
          uint256 internal preMigrationBalance;
          // User distribution
          bool internal userDistributed;
          uint256 internal userDistributeTime;
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      pragma solidity >0.5.0 <0.9.0;
      // SPDX-License-Identifier: GPL-3.0-only
      interface RocketMinipoolBaseInterface {
          function initialise(address _rocketStorage, address _nodeAddress) external;
          function delegateUpgrade() external;
          function delegateRollback() external;
          function setUseLatestDelegate(bool _setting) external;
          function getUseLatestDelegate() external view returns (bool);
          function getDelegate() external view returns (address);
          function getPreviousDelegate() external view returns (address);
          function getEffectiveDelegate() external view returns (address);
      }
      /**
        *       .
        *      / \\
        *     |.'.|
        *     |'.'|
        *   ,'|   |`.
        *  |,-'-|-'-.|
        *   __|_| |         _        _      _____           _
        *  | ___ \\|        | |      | |    | ___ \\         | |
        *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
        *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
        *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
        *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
        * +---------------------------------------------------+
        * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
        * +---------------------------------------------------+
        *
        *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
        *  decentralised, trustless and compatible with staking in Ethereum 2.0.
        *
        *  For more information about Rocket Pool, visit https://rocketpool.net
        *
        *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
        *
        */
      // SPDX-License-Identifier: GPL-3.0-only
      pragma solidity 0.7.6;
      import "./RocketMinipoolStorageLayout.sol";
      import "../../interface/RocketStorageInterface.sol";
      import "../../interface/minipool/RocketMinipoolBaseInterface.sol";
      /// @notice Contains the initialisation and delegate upgrade logic for minipools
      contract RocketMinipoolBase is RocketMinipoolBaseInterface, RocketMinipoolStorageLayout {
          // Events
          event EtherReceived(address indexed from, uint256 amount, uint256 time);
          event DelegateUpgraded(address oldDelegate, address newDelegate, uint256 time);
          event DelegateRolledBack(address oldDelegate, address newDelegate, uint256 time);
          // Store a reference to the address of RocketMinipoolBase itself to prevent direct calls to this contract
          address immutable self;
          constructor () {
              self = address(this);
          }
          /// @dev Prevent direct calls to this contract
          modifier notSelf() {
              require(address(this) != self);
              _;
          }
          /// @dev Only allow access from the owning node address
          modifier onlyMinipoolOwner() {
              // Only the node operator can upgrade
              address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(nodeAddress);
              require(msg.sender == nodeAddress || msg.sender == withdrawalAddress, "Only the node operator can access this method");
              _;
          }
          /// @notice Sets up starting delegate contract and then delegates initialisation to it
          function initialise(address _rocketStorage, address _nodeAddress) external override notSelf {
              // Check input
              require(_nodeAddress != address(0), "Invalid node address");
              require(storageState == StorageState.Undefined, "Already initialised");
              // Set storage state to uninitialised
              storageState = StorageState.Uninitialised;
              // Set rocketStorage
              rocketStorage = RocketStorageInterface(_rocketStorage);
              // Set the current delegate
              address delegateAddress = getContractAddress("rocketMinipoolDelegate");
              rocketMinipoolDelegate = delegateAddress;
              // Check for contract existence
              require(contractExists(delegateAddress), "Delegate contract does not exist");
              // Call initialise on delegate
              (bool success, bytes memory data) = delegateAddress.delegatecall(abi.encodeWithSignature('initialise(address)', _nodeAddress));
              if (!success) { revert(getRevertMessage(data)); }
          }
          /// @notice Receive an ETH deposit
          receive() external payable notSelf {
              // Emit ether received event
              emit EtherReceived(msg.sender, msg.value, block.timestamp);
          }
          /// @notice Upgrade this minipool to the latest network delegate contract
          function delegateUpgrade() external override onlyMinipoolOwner notSelf {
              // Set previous address
              rocketMinipoolDelegatePrev = rocketMinipoolDelegate;
              // Set new delegate
              rocketMinipoolDelegate = getContractAddress("rocketMinipoolDelegate");
              // Verify
              require(rocketMinipoolDelegate != rocketMinipoolDelegatePrev, "New delegate is the same as the existing one");
              // Log event
              emit DelegateUpgraded(rocketMinipoolDelegatePrev, rocketMinipoolDelegate, block.timestamp);
          }
          /// @notice Rollback to previous delegate contract
          function delegateRollback() external override onlyMinipoolOwner notSelf {
              // Make sure they have upgraded before
              require(rocketMinipoolDelegatePrev != address(0x0), "Previous delegate contract is not set");
              // Store original
              address originalDelegate = rocketMinipoolDelegate;
              // Update delegate to previous and zero out previous
              rocketMinipoolDelegate = rocketMinipoolDelegatePrev;
              rocketMinipoolDelegatePrev = address(0x0);
              // Log event
              emit DelegateRolledBack(originalDelegate, rocketMinipoolDelegate, block.timestamp);
          }
          /// @notice Sets the flag to automatically use the latest delegate contract or not
          /// @param _setting If true, will always use the latest delegate contract
          function setUseLatestDelegate(bool _setting) external override onlyMinipoolOwner notSelf {
              useLatestDelegate = _setting;
          }
          /// @notice Returns true if this minipool always uses the latest delegate contract
          function getUseLatestDelegate() external override view returns (bool) {
              return useLatestDelegate;
          }
          /// @notice Returns the address of the minipool's stored delegate
          function getDelegate() external override view returns (address) {
              return rocketMinipoolDelegate;
          }
          /// @notice Returns the address of the minipool's previous delegate (or address(0) if not set)
          function getPreviousDelegate() external override view returns (address) {
              return rocketMinipoolDelegatePrev;
          }
          /// @notice Returns the delegate which will be used when calling this minipool taking into account useLatestDelegate setting
          function getEffectiveDelegate() external override view returns (address) {
              return useLatestDelegate ? getContractAddress("rocketMinipoolDelegate") : rocketMinipoolDelegate;
          }
          /// @notice Delegates all calls to minipool delegate contract (or latest if flag is set)
          fallback(bytes calldata _input) external payable notSelf returns (bytes memory) {
              // If useLatestDelegate is set, use the latest delegate contract
              address delegateContract = useLatestDelegate ? getContractAddress("rocketMinipoolDelegate") : rocketMinipoolDelegate;
              // Check for contract existence
              require(contractExists(delegateContract), "Delegate contract does not exist");
              // Execute delegatecall
              (bool success, bytes memory data) = delegateContract.delegatecall(_input);
              if (!success) { revert(getRevertMessage(data)); }
              return data;
          }
          /// @dev Get the address of a Rocket Pool network contract
          function getContractAddress(string memory _contractName) private view returns (address) {
              address contractAddress = rocketStorage.getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
              require(contractAddress != address(0x0), "Contract not found");
              return contractAddress;
          }
          /// @dev Get a revert message from delegatecall return data
          function getRevertMessage(bytes memory _returnData) private pure returns (string memory) {
              if (_returnData.length < 68) { return "Transaction reverted silently"; }
              assembly {
                  _returnData := add(_returnData, 0x04)
              }
              return abi.decode(_returnData, (string));
          }
          /// @dev Returns true if contract exists at _contractAddress (if called during that contract's construction it will return a false negative)
          function contractExists(address _contractAddress) private view returns (bool) {
              uint32 codeSize;
              assembly {
                  codeSize := extcodesize(_contractAddress)
              }
              return codeSize > 0;
          }
      }
      

      File 3 of 3: 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;
      }