ETH Price: $4,123.32 (-2.58%)

Transaction Decoder

Block:
23573945 at Oct-14-2025 05:46:11 AM +UTC
Transaction Fee:
0.000103653823368864 ETH $0.43
Gas Used:
208,662 Gas / 0.496754672 Gwei

Emitted Events:

288 RocketTokenRETH.Transfer( from=0x0000000000000000000000000000000000000000, to=[Sender] 0xad314e1c16a58114e48acfad061e1e21a950d65d, value=87057135948275483 )
289 RocketTokenRETH.TokensMinted( to=[Sender] 0xad314e1c16a58114e48acfad061e1e21a950d65d, amount=87057135948275483, ethAmount=99950000000000000, time=1760420771 )
290 RocketDepositPool.DepositReceived( from=[Sender] 0xad314e1c16a58114e48acfad061e1e21a950d65d, amount=100000000000000000, time=1760420771 )
291 RocketVault.EtherDeposited( 0xbf25d6cb74c97a403cfab1c4c0abc9ffe3edd964de9924de0565f5ffe3d6ca79, 0xd76aaac3ecd5ced13bbab3b240a426352f76a6fffd583c3b15f4ddae2b754e4e, 000000000000000000000000000000000000000000000000016345785d8a0000, 0000000000000000000000000000000000000000000000000000000068ede3a3 )

Account State Difference:

  Address   Before After State Difference Code
0x3bDC69C4...636b469d6
(Rocket Pool: Vault)
351.84049921402034868 Eth351.94049921402034868 Eth0.1
(Titan Builder)
16.197540320447218895 Eth16.197589973155324109 Eth0.000049652708105214
0xAD314e1c...1A950d65D
0.144455775159105957 Eth
Nonce: 87
0.044352121335737093 Eth
Nonce: 88
0.100103653823368864
0xae78736C...E74Fc6393

Execution Trace

ETH 0.1 RocketDepositPool.CALL( )
  • RocketStorage.getAddress( _key=65DD923DDFC8D8AE6088F80077201D2403CBD565F0BA25E09841E2799EC90BB2 ) => ( r=0xDD3f50F8A6CafbE9b31a427582963f465E745AF8 )
  • RocketStorage.getAddress( _key=876D8A498B5341A6B5897A8239BFB0347E2B8D81FE9401D355C1E4B0ECEBEDAA ) => ( r=0xD846AA34caEf083DC4797d75096F60b6E08B7418 )
  • RocketDAOProtocolSettingsDeposit.STATICCALL( )
    • RocketStorage.getBool( _key=4F8D6202B5E247B85E44F30A9430B6E08B34FA8E958FFCF5F1E41956CC0D7E1F ) => ( r=True )
    • RocketDAOProtocolSettingsDeposit.STATICCALL( )
      • RocketStorage.getUint( _key=6F05C274EC0CB997E9EDF9AAAA45BFC6D473F896318DE35ADC4DADB0D137D240 ) => ( r=10000000000000000 )
      • RocketVault.balanceOf( _networkContractName=rocketDepositPool ) => ( 26958788797771120976 )
      • RocketDAOProtocolSettingsDeposit.STATICCALL( )
        • RocketStorage.getUint( _key=D487F0C76DC5563EABA9729FB4385F066098A27197F8E13CA686D12E073885D2 ) => ( r=18000000000000000000000 )
        • RocketDAOProtocolSettingsDeposit.STATICCALL( )
          • RocketStorage.getUint( _key=EE1B2D062BC9318204362E343B5925EEFF06035FE194C84EE300A29B5AC8CDE3 ) => ( r=500000000000000 )
          • RocketTokenRETH.mint( _ethAmount=99950000000000000, _to=0xAD314e1c16A58114e48aCFad061e1E21A950d65D )
            • RocketStorage.getAddress( _key=65DD923DDFC8D8AE6088F80077201D2403CBD565F0BA25E09841E2799EC90BB2 ) => ( r=0xDD3f50F8A6CafbE9b31a427582963f465E745AF8 )
            • RocketStorage.getAddress( _key=7630E125F1C009E5FC974F6DAE77C6D5B1802979B36E6D7145463C21782AF01E ) => ( r=0x6Cc65bF618F55ce2433f9D8d827Fc44117D81399 )
            • RocketNetworkBalances.STATICCALL( )
              • RocketStorage.getUint( _key=9DC185B46ED0F11D151F055E45FDE635375A9680C34E501B43A82EB6C09C0951 ) => ( r=448963863291362164527431 )
              • RocketNetworkBalances.STATICCALL( )
                • RocketStorage.getUint( _key=5B3A7B8BDDE2122FAD4DC45E51AE0C5CEDC887473A999474F2EAD5A8FAADFE3C ) => ( r=391050606127254475123558 )
                • ETH 0.1 RocketVault.CALL( )
                  • RocketStorage.getBool( _key=D5408E125710EAB17CDF2147135EF16391CA4FD37D945EBCC411F1AEA89E33E1 ) => ( r=True )
                  • RocketStorage.getString( _key=EFA313C50E423AA5F127DEDEC88AF5265A323D4C42F1A774AC98381AA4765641 ) => ( rocketDepositPool )
                  • RocketDAOProtocolSettingsDeposit.STATICCALL( )
                    • RocketStorage.getBool( _key=7EC24CF490A1FFB5C13392646C058364D3C33BB049057DA2EEE3F3C96C7F81CE ) => ( r=True )
                    • RocketStorage.getAddress( _key=7F602045A039DA8AC7709E3205CD54DB6D7D9A1113DFF494A3B44D1CABA908CA ) => ( r=0x9e966733e3E9BFA56aF95f762921859417cF6FaA )
                    • RocketMinipoolQueue.STATICCALL( )
                      • RocketStorage.getAddress( _key=2ADDCCD64DD43C4EF1213C10626C6170F7F9BB5F4A96DFBBABDDCBED2B170FC4 ) => ( r=0x44E31944E1A6F3b8F805E105B130F8bdb7E2EBd8 )
                      • AddressQueueStorage.getLength( _key=6EEA9E53DC9C4FB5C4B0BA0E9DB7370A823B1513965347E82945EB8966218188 ) => ( 0 )
                        • RocketStorage.getUint( _key=95241176D02B112B4675AB170EC86B6AFAA12950DD1E0EF2FEC43D18C303E299 ) => ( r=13619 )
                        • RocketStorage.getUint( _key=F1F06692C94A9F7B9AC29EF95E4AD442A08CD918141BBDB78EA58B554199BADD ) => ( r=13619 )
                        • RocketStorage.getAddress( _key=2ADDCCD64DD43C4EF1213C10626C6170F7F9BB5F4A96DFBBABDDCBED2B170FC4 ) => ( r=0x44E31944E1A6F3b8F805E105B130F8bdb7E2EBd8 )
                        • AddressQueueStorage.getLength( _key=885ADB3A1C7CF88A1F3627E1265F3090CD728E0FC96765288E91E8777267FF78 ) => ( 0 )
                          • RocketStorage.getUint( _key=D8B6A4977457C014E88D4551BB15C633AC48CF3A509B7AD618D7F9C87179B9E2 ) => ( r=447 )
                          • RocketStorage.getUint( _key=9C44AF08C16FB81C92299114DC1604F94FF10E4151B35DEE89C1E453B52DDC8F ) => ( r=447 )
                          • RocketStorage.getAddress( _key=CABD9A4F404C4FFB362A3C40647A1A12F3BDAA2AD3BBCDB92EA716C2EA3FF22B ) => ( r=0xA416A7a07925d60F794E20532bc730749611A220 )
                          • RocketDAOProtocolSettingsDeposit.STATICCALL( )
                            • RocketStorage.getUint( _key=7084F8410C25F824B2C9BCB3257747C0BED19F9A4A062A2CF00B381903C57091 ) => ( r=90 )
                            • RocketDAOProtocolSettingsMinipool.STATICCALL( )
                            • RocketVault.balanceOf( _networkContractName=rocketDepositPool ) => ( 27058788797771120976 )
                            • RocketDAOProtocolSettingsDeposit.STATICCALL( )
                              • RocketStorage.getUint( _key=17230967DC9606FD2F86361D62CA142D2605B4CC343C53D89C4643940F34EA05 ) => ( r=2 )
                              • RocketMinipoolQueue.dequeueMinipools( _maxToDequeue=0 ) => ( minipoolAddress=[] )
                                • RocketStorage.getAddress( _key=7F602045A039DA8AC7709E3205CD54DB6D7D9A1113DFF494A3B44D1CABA908CA ) => ( r=0x9e966733e3E9BFA56aF95f762921859417cF6FaA )
                                • RocketStorage.getAddress( _key=65DD923DDFC8D8AE6088F80077201D2403CBD565F0BA25E09841E2799EC90BB2 ) => ( r=0xDD3f50F8A6CafbE9b31a427582963f465E745AF8 )
                                • RocketStorage.getAddress( _key=2ADDCCD64DD43C4EF1213C10626C6170F7F9BB5F4A96DFBBABDDCBED2B170FC4 ) => ( r=0x44E31944E1A6F3b8F805E105B130F8bdb7E2EBd8 )
                                • AddressQueueStorage.getLength( _key=A7C30D79BAC38383B63CF527B2A68C8A7EFFF3BA22DFD5B81D98030643EF0FCA ) => ( 135 )
                                  • RocketStorage.getUint( _key=8865F902AF621B4F2CF327D5B224395315261CF0162DFF451FFAF06FA690A709 ) => ( r=27934 )
                                  • RocketStorage.getUint( _key=209FE6DEF179A25C51657DA761F6D397B1299F7424F3BB336ED82F6DC3AA0EEA ) => ( r=28069 )
                                    File 1 of 9: RocketDepositPool
                                    // 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;
                                    /**
                                     * @title SignedSafeMath
                                     * @dev Signed math operations with safety checks that revert on error.
                                     */
                                    library SignedSafeMath {
                                        int256 constant private _INT256_MIN = -2**255;
                                        /**
                                         * @dev Returns the multiplication of two signed integers, reverting on
                                         * overflow.
                                         *
                                         * Counterpart to Solidity's `*` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - Multiplication cannot overflow.
                                         */
                                        function mul(int256 a, int256 b) internal pure returns (int256) {
                                            // 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 0;
                                            }
                                            require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");
                                            int256 c = a * b;
                                            require(c / a == b, "SignedSafeMath: multiplication overflow");
                                            return c;
                                        }
                                        /**
                                         * @dev Returns the integer division of two signed integers. Reverts 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(int256 a, int256 b) internal pure returns (int256) {
                                            require(b != 0, "SignedSafeMath: division by zero");
                                            require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");
                                            int256 c = a / b;
                                            return c;
                                        }
                                        /**
                                         * @dev Returns the subtraction of two signed integers, reverting on
                                         * overflow.
                                         *
                                         * Counterpart to Solidity's `-` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - Subtraction cannot overflow.
                                         */
                                        function sub(int256 a, int256 b) internal pure returns (int256) {
                                            int256 c = a - b;
                                            require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");
                                            return c;
                                        }
                                        /**
                                         * @dev Returns the addition of two signed integers, reverting on
                                         * overflow.
                                         *
                                         * Counterpart to Solidity's `+` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - Addition cannot overflow.
                                         */
                                        function add(int256 a, int256 b) internal pure returns (int256) {
                                            int256 c = a + b;
                                            require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");
                                            return c;
                                        }
                                    }
                                    // SPDX-License-Identifier: MIT
                                    pragma solidity >=0.6.0 <0.8.0;
                                    /**
                                     * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
                                     * checks.
                                     *
                                     * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
                                     * easily result in undesired exploitation or bugs, since developers usually
                                     * assume that overflows raise errors. `SafeCast` restores this intuition by
                                     * reverting the transaction when such 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.
                                     *
                                     * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
                                     * all math on `uint256` and `int256` and then downcasting.
                                     */
                                    library SafeCast {
                                        /**
                                         * @dev Returns the downcasted uint128 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint128).
                                         *
                                         * Counterpart to Solidity's `uint128` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 128 bits
                                         */
                                        function toUint128(uint256 value) internal pure returns (uint128) {
                                            require(value < 2**128, "SafeCast: value doesn\\'t fit in 128 bits");
                                            return uint128(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted uint64 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint64).
                                         *
                                         * Counterpart to Solidity's `uint64` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 64 bits
                                         */
                                        function toUint64(uint256 value) internal pure returns (uint64) {
                                            require(value < 2**64, "SafeCast: value doesn\\'t fit in 64 bits");
                                            return uint64(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted uint32 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint32).
                                         *
                                         * Counterpart to Solidity's `uint32` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 32 bits
                                         */
                                        function toUint32(uint256 value) internal pure returns (uint32) {
                                            require(value < 2**32, "SafeCast: value doesn\\'t fit in 32 bits");
                                            return uint32(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted uint16 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint16).
                                         *
                                         * Counterpart to Solidity's `uint16` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 16 bits
                                         */
                                        function toUint16(uint256 value) internal pure returns (uint16) {
                                            require(value < 2**16, "SafeCast: value doesn\\'t fit in 16 bits");
                                            return uint16(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted uint8 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint8).
                                         *
                                         * Counterpart to Solidity's `uint8` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 8 bits.
                                         */
                                        function toUint8(uint256 value) internal pure returns (uint8) {
                                            require(value < 2**8, "SafeCast: value doesn\\'t fit in 8 bits");
                                            return uint8(value);
                                        }
                                        /**
                                         * @dev Converts a signed int256 into an unsigned uint256.
                                         *
                                         * Requirements:
                                         *
                                         * - input must be greater than or equal to 0.
                                         */
                                        function toUint256(int256 value) internal pure returns (uint256) {
                                            require(value >= 0, "SafeCast: value must be positive");
                                            return uint256(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int128 from int256, reverting on
                                         * overflow (when the input is less than smallest int128 or
                                         * greater than largest int128).
                                         *
                                         * Counterpart to Solidity's `int128` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 128 bits
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt128(int256 value) internal pure returns (int128) {
                                            require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\\'t fit in 128 bits");
                                            return int128(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int64 from int256, reverting on
                                         * overflow (when the input is less than smallest int64 or
                                         * greater than largest int64).
                                         *
                                         * Counterpart to Solidity's `int64` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 64 bits
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt64(int256 value) internal pure returns (int64) {
                                            require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\\'t fit in 64 bits");
                                            return int64(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int32 from int256, reverting on
                                         * overflow (when the input is less than smallest int32 or
                                         * greater than largest int32).
                                         *
                                         * Counterpart to Solidity's `int32` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 32 bits
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt32(int256 value) internal pure returns (int32) {
                                            require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\\'t fit in 32 bits");
                                            return int32(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int16 from int256, reverting on
                                         * overflow (when the input is less than smallest int16 or
                                         * greater than largest int16).
                                         *
                                         * Counterpart to Solidity's `int16` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 16 bits
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt16(int256 value) internal pure returns (int16) {
                                            require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\\'t fit in 16 bits");
                                            return int16(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int8 from int256, reverting on
                                         * overflow (when the input is less than smallest int8 or
                                         * greater than largest int8).
                                         *
                                         * Counterpart to Solidity's `int8` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 8 bits.
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt8(int256 value) internal pure returns (int8) {
                                            require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\\'t fit in 8 bits");
                                            return int8(value);
                                        }
                                        /**
                                         * @dev Converts an unsigned uint256 into a signed int256.
                                         *
                                         * Requirements:
                                         *
                                         * - input must be less than or equal to maxInt256.
                                         */
                                        function toInt256(uint256 value) internal pure returns (int256) {
                                            require(value < 2**255, "SafeCast: value doesn't fit in an int256");
                                            return int256(value);
                                        }
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
                                      * +---------------------------------------------------+
                                      *
                                      *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
                                      *  decentralised, trustless and compatible with staking in Ethereum 2.0.
                                      *
                                      *  For more information about Rocket Pool, visit https://rocketpool.net
                                      *
                                      *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
                                      *
                                      */
                                    pragma solidity >0.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
                                    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); }
                                    }
                                    // 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;
                                        }
                                    }
                                    // 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);
                                        }
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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
                                    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 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 RocketVaultWithdrawerInterface {
                                        function receiveVaultWithdrawalETH() external payable; 
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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 RocketDepositPoolInterface {
                                        function getBalance() external view returns (uint256);
                                        function getNodeBalance() external view returns (uint256);
                                        function getUserBalance() external view returns (int256);
                                        function getExcessBalance() external view returns (uint256);
                                        function deposit() external payable;
                                        function getMaximumDepositAmount() external view returns (uint256);
                                        function nodeDeposit(uint256 _totalAmount) external payable;
                                        function nodeCreditWithdrawal(uint256 _amount) external;
                                        function recycleDissolvedDeposit() external payable;
                                        function recycleExcessCollateral() external payable;
                                        function recycleLiquidatedStake() external payable;
                                        function assignDeposits() external;
                                        function maybeAssignDeposits() external returns (bool);
                                        function withdrawExcessBalance(uint256 _amount) external;
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    import "../../types/MinipoolDeposit.sol";
                                    import "../../types/MinipoolStatus.sol";
                                    import "../RocketStorageInterface.sol";
                                    interface RocketMinipoolInterface {
                                        function version() external view returns (uint8);
                                        function initialise(address _nodeAddress) external;
                                        function getStatus() external view returns (MinipoolStatus);
                                        function getFinalised() external view returns (bool);
                                        function getStatusBlock() external view returns (uint256);
                                        function getStatusTime() external view returns (uint256);
                                        function getScrubVoted(address _member) external view returns (bool);
                                        function getDepositType() external view returns (MinipoolDeposit);
                                        function getNodeAddress() external view returns (address);
                                        function getNodeFee() external view returns (uint256);
                                        function getNodeDepositBalance() external view returns (uint256);
                                        function getNodeRefundBalance() external view returns (uint256);
                                        function getNodeDepositAssigned() external view returns (bool);
                                        function getPreLaunchValue() external view returns (uint256);
                                        function getNodeTopUpValue() external view returns (uint256);
                                        function getVacant() external view returns (bool);
                                        function getPreMigrationBalance() external view returns (uint256);
                                        function getUserDistributed() external view returns (bool);
                                        function getUserDepositBalance() external view returns (uint256);
                                        function getUserDepositAssigned() external view returns (bool);
                                        function getUserDepositAssignedTime() external view returns (uint256);
                                        function getTotalScrubVotes() external view returns (uint256);
                                        function calculateNodeShare(uint256 _balance) external view returns (uint256);
                                        function calculateUserShare(uint256 _balance) external view returns (uint256);
                                        function preDeposit(uint256 _bondingValue, bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot) external payable;
                                        function deposit() external payable;
                                        function userDeposit() external payable;
                                        function distributeBalance(bool _rewardsOnly) external;
                                        function beginUserDistribute() external;
                                        function userDistributeAllowed() external view returns (bool);
                                        function refund() external;
                                        function slash() external;
                                        function finalise() external;
                                        function canStake() external view returns (bool);
                                        function canPromote() external view returns (bool);
                                        function stake(bytes calldata _validatorSignature, bytes32 _depositDataRoot) external;
                                        function prepareVacancy(uint256 _bondAmount, uint256 _currentBalance) external;
                                        function promote() external;
                                        function dissolve() external;
                                        function close() external;
                                        function voteScrub() external;
                                        function reduceBondAmount() external;
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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
                                    import "../../types/MinipoolDeposit.sol";
                                    interface RocketMinipoolQueueInterface {
                                        function getTotalLength() external view returns (uint256);
                                        function getContainsLegacy() external view returns (bool);
                                        function getLengthLegacy(MinipoolDeposit _depositType) external view returns (uint256);
                                        function getLength() external view returns (uint256);
                                        function getTotalCapacity() external view returns (uint256);
                                        function getEffectiveCapacity() external view returns (uint256);
                                        function getNextCapacityLegacy() external view returns (uint256);
                                        function getNextDepositLegacy() external view returns (MinipoolDeposit, uint256);
                                        function enqueueMinipool(address _minipool) external;
                                        function dequeueMinipoolByDepositLegacy(MinipoolDeposit _depositType) external returns (address minipoolAddress);
                                        function dequeueMinipools(uint256 _maxToDequeue) external returns (address[] memory minipoolAddress);
                                        function removeMinipool(MinipoolDeposit _depositType) external;
                                        function getMinipoolAt(uint256 _index) external view returns(address);
                                        function getMinipoolPosition(address _minipool) external view returns (int256);
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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 RocketDAOProtocolSettingsDepositInterface {
                                        function getDepositEnabled() external view returns (bool);
                                        function getAssignDepositsEnabled() external view returns (bool);
                                        function getMinimumDeposit() external view returns (uint256);
                                        function getMaximumDepositPoolSize() external view returns (uint256);
                                        function getMaximumDepositAssignments() external view returns (uint256);
                                        function getMaximumDepositSocialisedAssignments() external view returns (uint256);
                                        function getDepositFee() external view returns (uint256);
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
                                      * +---------------------------------------------------+
                                      *
                                      *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
                                      *  decentralised, trustless and compatible with staking in Ethereum 2.0.
                                      *
                                      *  For more information about Rocket Pool, visit https://rocketpool.net
                                      *
                                      *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
                                      *
                                      */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    import "../../../../types/MinipoolDeposit.sol";
                                    interface RocketDAOProtocolSettingsMinipoolInterface {
                                        function getLaunchBalance() external view returns (uint256);
                                        function getPreLaunchValue() external pure returns (uint256);
                                        function getDepositUserAmount(MinipoolDeposit _depositType) external view returns (uint256);
                                        function getFullDepositUserAmount() external view returns (uint256);
                                        function getHalfDepositUserAmount() external view returns (uint256);
                                        function getVariableDepositAmount() external view returns (uint256);
                                        function getSubmitWithdrawableEnabled() external view returns (bool);
                                        function getBondReductionEnabled() external view returns (bool);
                                        function getLaunchTimeout() external view returns (uint256);
                                        function getMaximumCount() external view returns (uint256);
                                        function isWithinUserDistributeWindow(uint256 _time) external view returns (bool);
                                        function hasUserDistributeWindowPassed(uint256 _time) external view returns (bool);
                                        function getUserDistributeWindowStart() external view returns (uint256);
                                        function getUserDistributeWindowLength() external view returns (uint256);
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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 RocketDAOProtocolSettingsNetworkInterface {
                                        function getNodeConsensusThreshold() external view returns (uint256);
                                        function getNodePenaltyThreshold() external view returns (uint256);
                                        function getPerPenaltyRate() external view returns (uint256);
                                        function getSubmitBalancesEnabled() external view returns (bool);
                                        function getSubmitBalancesFrequency() external view returns (uint256);
                                        function getSubmitPricesEnabled() external view returns (bool);
                                        function getSubmitPricesFrequency() external view returns (uint256);
                                        function getMinimumNodeFee() external view returns (uint256);
                                        function getTargetNodeFee() external view returns (uint256);
                                        function getMaximumNodeFee() external view returns (uint256);
                                        function getNodeFeeDemandRange() external view returns (uint256);
                                        function getTargetRethCollateralRate() external view returns (uint256);
                                        function getRethDepositDelay() external view returns (uint256);
                                        function getSubmitRewardsEnabled() external view returns (bool);
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
                                      * +---------------------------------------------------+
                                      *
                                      *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
                                      *  decentralised, trustless and compatible with staking in Ethereum 2.0.
                                      *
                                      *  For more information about Rocket Pool, visit https://rocketpool.net
                                      *
                                      *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
                                      *
                                      */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
                                    interface RocketTokenRETHInterface is IERC20 {
                                        function getEthValue(uint256 _rethAmount) external view returns (uint256);
                                        function getRethValue(uint256 _ethAmount) external view returns (uint256);
                                        function getExchangeRate() external view returns (uint256);
                                        function getTotalCollateral() external view returns (uint256);
                                        function getCollateralRate() external view returns (uint256);
                                        function depositExcess() external payable;
                                        function depositExcessCollateral() external;
                                        function mint(uint256 _ethAmount, address _to) external;
                                        function burn(uint256 _rethAmount) external;
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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 "@openzeppelin/contracts/math/SafeMath.sol";
                                    import "@openzeppelin/contracts/math/SignedSafeMath.sol";
                                    import "@openzeppelin/contracts/utils/SafeCast.sol";
                                    import "../RocketBase.sol";
                                    import "../../interface/RocketVaultInterface.sol";
                                    import "../../interface/RocketVaultWithdrawerInterface.sol";
                                    import "../../interface/deposit/RocketDepositPoolInterface.sol";
                                    import "../../interface/minipool/RocketMinipoolInterface.sol";
                                    import "../../interface/minipool/RocketMinipoolQueueInterface.sol";
                                    import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsDepositInterface.sol";
                                    import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsMinipoolInterface.sol";
                                    import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNetworkInterface.sol";
                                    import "../../interface/token/RocketTokenRETHInterface.sol";
                                    import "../../types/MinipoolDeposit.sol";
                                    /// @notice Accepts user deposits and mints rETH; handles assignment of deposited ETH to minipools
                                    contract RocketDepositPool is RocketBase, RocketDepositPoolInterface, RocketVaultWithdrawerInterface {
                                        // Libs
                                        using SafeMath for uint256;
                                        using SignedSafeMath for int256;
                                        using SafeCast for uint256;
                                        // Immutables
                                        RocketVaultInterface immutable rocketVault;
                                        RocketTokenRETHInterface immutable rocketTokenRETH;
                                        // Events
                                        event DepositReceived(address indexed from, uint256 amount, uint256 time);
                                        event DepositRecycled(address indexed from, uint256 amount, uint256 time);
                                        event DepositAssigned(address indexed minipool, uint256 amount, uint256 time);
                                        event ExcessWithdrawn(address indexed to, uint256 amount, uint256 time);
                                        // Structs
                                        struct MinipoolAssignment {
                                            address minipoolAddress;
                                            uint256 etherAssigned;
                                        }
                                        // Modifiers
                                        modifier onlyThisLatestContract() {
                                            // Compiler can optimise out this keccak at compile time
                                            require(address(this) == getAddress(keccak256("contract.addressrocketDepositPool")), "Invalid or outdated contract");
                                            _;
                                        }
                                        constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
                                            version = 3;
                                            // Pre-retrieve non-upgradable contract addresses to save gas
                                            rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
                                            rocketTokenRETH = RocketTokenRETHInterface(getContractAddress("rocketTokenRETH"));
                                        }
                                        /// @notice Returns the current deposit pool balance
                                        function getBalance() override public view returns (uint256) {
                                            return rocketVault.balanceOf("rocketDepositPool");
                                        }
                                        /// @notice Returns the amount of ETH contributed to the deposit pool by node operators waiting in the queue
                                        function getNodeBalance() override public view returns (uint256) {
                                            return getUint("deposit.pool.node.balance");
                                        }
                                        /// @notice Returns the user owned portion of the deposit pool (negative indicates more ETH has been "lent" to the
                                        ///         deposit pool by node operators in the queue than is available from user deposits)
                                        function getUserBalance() override public view returns (int256) {
                                            return getBalance().toInt256().sub(getNodeBalance().toInt256());
                                        }
                                        /// @notice Excess deposit pool balance (in excess of minipool queue capacity)
                                        function getExcessBalance() override public view returns (uint256) {
                                            // Get minipool queue capacity
                                            RocketMinipoolQueueInterface rocketMinipoolQueue = RocketMinipoolQueueInterface(getContractAddress("rocketMinipoolQueue"));
                                            uint256 minipoolCapacity = rocketMinipoolQueue.getEffectiveCapacity();
                                            uint256 balance = getBalance();
                                            // Calculate and return
                                            if (minipoolCapacity >= balance) { return 0; }
                                            else { return balance.sub(minipoolCapacity); }
                                        }
                                        /// @dev Callback required to receive ETH withdrawal from the vault
                                        function receiveVaultWithdrawalETH() override external payable onlyThisLatestContract onlyLatestContract("rocketVault", msg.sender) {}
                                        /// @notice Deposits ETH into Rocket Pool and mints the corresponding amount of rETH to the caller
                                        function deposit() override external payable onlyThisLatestContract {
                                            // Check deposit settings
                                            RocketDAOProtocolSettingsDepositInterface rocketDAOProtocolSettingsDeposit = RocketDAOProtocolSettingsDepositInterface(getContractAddress("rocketDAOProtocolSettingsDeposit"));
                                            require(rocketDAOProtocolSettingsDeposit.getDepositEnabled(), "Deposits into Rocket Pool are currently disabled");
                                            require(msg.value >= rocketDAOProtocolSettingsDeposit.getMinimumDeposit(), "The deposited amount is less than the minimum deposit size");
                                            /*
                                                Check if deposit exceeds limit based on current deposit size and minipool queue capacity.
                                                The deposit pool can, at most, accept a deposit that, after assignments, matches ETH to every minipool in
                                                the queue and leaves the deposit pool with maximumDepositPoolSize ETH.
                                                capacityNeeded = depositPoolBalance + msg.value
                                                maxCapacity = maximumDepositPoolSize + queueEffectiveCapacity
                                                assert(capacityNeeded <= maxCapacity)
                                            */
                                            uint256 capacityNeeded = getBalance().add(msg.value);
                                            uint256 maxDepositPoolSize = rocketDAOProtocolSettingsDeposit.getMaximumDepositPoolSize();
                                            if (capacityNeeded > maxDepositPoolSize) {
                                                // Doing a conditional require() instead of a single one optimises for the common
                                                // case where capacityNeeded fits in the deposit pool without looking at the queue
                                                if (rocketDAOProtocolSettingsDeposit.getAssignDepositsEnabled()) {
                                                    RocketMinipoolQueueInterface rocketMinipoolQueue = RocketMinipoolQueueInterface(getContractAddress("rocketMinipoolQueue"));
                                                    require(capacityNeeded <= maxDepositPoolSize.add(rocketMinipoolQueue.getEffectiveCapacity()),
                                                        "The deposit pool size after depositing (and matching with minipools) exceeds the maximum size");
                                                } else {
                                                    revert("The deposit pool size after depositing exceeds the maximum size");
                                                }
                                            }
                                            // Calculate deposit fee
                                            uint256 depositFee = msg.value.mul(rocketDAOProtocolSettingsDeposit.getDepositFee()).div(calcBase);
                                            uint256 depositNet = msg.value.sub(depositFee);
                                            // Mint rETH to user account
                                            rocketTokenRETH.mint(depositNet, msg.sender);
                                            // Emit deposit received event
                                            emit DepositReceived(msg.sender, msg.value, block.timestamp);
                                            // Process deposit
                                            processDeposit(rocketDAOProtocolSettingsDeposit);
                                        }
                                        /// @notice Returns the maximum amount that can be accepted into the deposit pool at this time in wei
                                        function getMaximumDepositAmount() override external view returns (uint256) {
                                            RocketDAOProtocolSettingsDepositInterface rocketDAOProtocolSettingsDeposit = RocketDAOProtocolSettingsDepositInterface(getContractAddress("rocketDAOProtocolSettingsDeposit"));
                                            // If deposits are enabled max deposit is 0
                                            if (!rocketDAOProtocolSettingsDeposit.getDepositEnabled()) {
                                                return 0;
                                            }
                                            uint256 depositPoolBalance = getBalance();
                                            uint256 maxCapacity = rocketDAOProtocolSettingsDeposit.getMaximumDepositPoolSize();
                                            // When assignments are enabled, we can accept the max amount plus whatever space is available in the minipool queue
                                            if (rocketDAOProtocolSettingsDeposit.getAssignDepositsEnabled()) {
                                                RocketMinipoolQueueInterface rocketMinipoolQueue = RocketMinipoolQueueInterface(getContractAddress("rocketMinipoolQueue"));
                                                maxCapacity = maxCapacity.add(rocketMinipoolQueue.getEffectiveCapacity());
                                            }
                                            // Check we aren't already over
                                            if (depositPoolBalance >= maxCapacity) {
                                                return 0;
                                            }
                                            return maxCapacity.sub(depositPoolBalance);
                                        }
                                        /// @dev Accepts ETH deposit from the node deposit contract (does not mint rETH)
                                        /// @param _totalAmount The total node deposit amount including any credit balance used
                                        function nodeDeposit(uint256 _totalAmount) override external payable onlyThisLatestContract onlyLatestContract("rocketNodeDeposit", msg.sender) {
                                            // Deposit ETH into the vault
                                            if (msg.value > 0) {
                                                rocketVault.depositEther{value: msg.value}();
                                            }
                                            // Increase recorded node balance
                                            addUint("deposit.pool.node.balance", _totalAmount);
                                        }
                                        /// @dev Withdraws ETH from the deposit pool to RocketNodeDeposit contract to be used for a new minipool
                                        /// @param _amount The amount of ETH to withdraw
                                        function nodeCreditWithdrawal(uint256 _amount) override external onlyThisLatestContract onlyLatestContract("rocketNodeDeposit", msg.sender) {
                                            // Withdraw ETH from the vault
                                            rocketVault.withdrawEther(_amount);
                                            // Send it to msg.sender (function modifier verifies msg.sender is RocketNodeDeposit)
                                            (bool success, ) = address(msg.sender).call{value: _amount}("");
                                            require(success, "Failed to send ETH");
                                        }
                                        /// @dev Recycle a deposit from a dissolved minipool
                                        function recycleDissolvedDeposit() override external payable onlyThisLatestContract onlyRegisteredMinipool(msg.sender) {
                                            // Load contracts
                                            RocketDAOProtocolSettingsDepositInterface rocketDAOProtocolSettingsDeposit = RocketDAOProtocolSettingsDepositInterface(getContractAddress("rocketDAOProtocolSettingsDeposit"));
                                            // Recycle ETH
                                            emit DepositRecycled(msg.sender, msg.value, block.timestamp);
                                            processDeposit(rocketDAOProtocolSettingsDeposit);
                                        }
                                        /// @dev Recycle excess ETH from the rETH token contract
                                        function recycleExcessCollateral() override external payable onlyThisLatestContract onlyLatestContract("rocketTokenRETH", msg.sender) {
                                            // Load contracts
                                            RocketDAOProtocolSettingsDepositInterface rocketDAOProtocolSettingsDeposit = RocketDAOProtocolSettingsDepositInterface(getContractAddress("rocketDAOProtocolSettingsDeposit"));
                                            // Recycle ETH
                                            emit DepositRecycled(msg.sender, msg.value, block.timestamp);
                                            processDeposit(rocketDAOProtocolSettingsDeposit);
                                        }
                                        /// @dev Recycle a liquidated RPL stake from a slashed minipool
                                        function recycleLiquidatedStake() override external payable onlyThisLatestContract onlyLatestContract("rocketAuctionManager", msg.sender) {
                                            // Load contracts
                                            RocketDAOProtocolSettingsDepositInterface rocketDAOProtocolSettingsDeposit = RocketDAOProtocolSettingsDepositInterface(getContractAddress("rocketDAOProtocolSettingsDeposit"));
                                            // Recycle ETH
                                            emit DepositRecycled(msg.sender, msg.value, block.timestamp);
                                            processDeposit(rocketDAOProtocolSettingsDeposit);
                                        }
                                        /// @dev Process a deposit
                                        function processDeposit(RocketDAOProtocolSettingsDepositInterface _rocketDAOProtocolSettingsDeposit) private {
                                            // Transfer ETH to vault
                                            rocketVault.depositEther{value: msg.value}();
                                            // Assign deposits if enabled
                                            _assignDeposits(_rocketDAOProtocolSettingsDeposit);
                                        }
                                        /// @notice Assign deposits to available minipools. Reverts if assigning deposits is disabled.
                                        function assignDeposits() override external onlyThisLatestContract {
                                            // Load contracts
                                            RocketDAOProtocolSettingsDepositInterface rocketDAOProtocolSettingsDeposit = RocketDAOProtocolSettingsDepositInterface(getContractAddress("rocketDAOProtocolSettingsDeposit"));
                                            // Revert if assigning is disabled
                                            require(_assignDeposits(rocketDAOProtocolSettingsDeposit), "Deposit assignments are currently disabled");
                                        }
                                        /// @dev Assign deposits to available minipools. Does nothing if assigning deposits is disabled.
                                        function maybeAssignDeposits() override external onlyThisLatestContract returns (bool) {
                                            // Load contracts
                                            RocketDAOProtocolSettingsDepositInterface rocketDAOProtocolSettingsDeposit = RocketDAOProtocolSettingsDepositInterface(getContractAddress("rocketDAOProtocolSettingsDeposit"));
                                            // Revert if assigning is disabled
                                            return _assignDeposits(rocketDAOProtocolSettingsDeposit);
                                        }
                                        /// @dev Assigns deposits to available minipools, returns false if assignment is currently disabled
                                        function _assignDeposits(RocketDAOProtocolSettingsDepositInterface _rocketDAOProtocolSettingsDeposit) private returns (bool) {
                                            // Check if assigning deposits is enabled
                                            if (!_rocketDAOProtocolSettingsDeposit.getAssignDepositsEnabled()) {
                                                return false;
                                            }
                                            // Load contracts
                                            RocketMinipoolQueueInterface rocketMinipoolQueue = RocketMinipoolQueueInterface(getContractAddress("rocketMinipoolQueue"));
                                            // Decide which queue processing implementation to use based on queue contents
                                            if (rocketMinipoolQueue.getContainsLegacy()) {
                                                return _assignDepositsLegacy(rocketMinipoolQueue, _rocketDAOProtocolSettingsDeposit);
                                            } else {
                                                return _assignDepositsNew(rocketMinipoolQueue, _rocketDAOProtocolSettingsDeposit);
                                            }
                                        }
                                        /// @dev Assigns deposits using the new minipool queue
                                        function _assignDepositsNew(RocketMinipoolQueueInterface _rocketMinipoolQueue, RocketDAOProtocolSettingsDepositInterface _rocketDAOProtocolSettingsDeposit) private returns (bool) {
                                            // Load contracts
                                            RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
                                            // Calculate the number of minipools to assign
                                            uint256 maxAssignments = _rocketDAOProtocolSettingsDeposit.getMaximumDepositAssignments();
                                            uint256 variableDepositAmount = rocketDAOProtocolSettingsMinipool.getVariableDepositAmount();
                                            uint256 scalingCount = msg.value.div(variableDepositAmount);
                                            uint256 totalEthCount = getBalance().div(variableDepositAmount);
                                            uint256 assignments = _rocketDAOProtocolSettingsDeposit.getMaximumDepositSocialisedAssignments().add(scalingCount);
                                            if (assignments > totalEthCount) {
                                                assignments = totalEthCount;
                                            }
                                            if (assignments > maxAssignments) {
                                                assignments = maxAssignments;
                                            }
                                            address[] memory minipools = _rocketMinipoolQueue.dequeueMinipools(assignments);
                                            if (minipools.length > 0){
                                                // Withdraw ETH from vault
                                                uint256 totalEther = minipools.length.mul(variableDepositAmount);
                                                rocketVault.withdrawEther(totalEther);
                                                uint256 nodeBalanceUsed = 0;
                                                // Loop over minipools and deposit the amount required to reach launch balance
                                                for (uint256 i = 0; i < minipools.length; i++) {
                                                    RocketMinipoolInterface minipool = RocketMinipoolInterface(minipools[i]);
                                                    // Assign deposit to minipool
                                                    minipool.deposit{value: variableDepositAmount}();
                                                    nodeBalanceUsed = nodeBalanceUsed.add(minipool.getNodeTopUpValue());
                                                    // Emit deposit assigned event
                                                    emit DepositAssigned(minipools[i], variableDepositAmount, block.timestamp);
                                                }
                                                // Decrease node balance
                                                subUint("deposit.pool.node.balance", nodeBalanceUsed);
                                            }
                                            return true;
                                        }
                                        /// @dev Assigns deposits using the legacy minipool queue
                                        function _assignDepositsLegacy(RocketMinipoolQueueInterface _rocketMinipoolQueue, RocketDAOProtocolSettingsDepositInterface _rocketDAOProtocolSettingsDeposit) private returns (bool) {
                                            // Load contracts
                                            RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
                                            // Setup initial variable values
                                            uint256 balance = getBalance();
                                            uint256 totalEther = 0;
                                            // Calculate minipool assignments
                                            uint256 maxAssignments = _rocketDAOProtocolSettingsDeposit.getMaximumDepositAssignments();
                                            MinipoolAssignment[] memory assignments = new MinipoolAssignment[](maxAssignments);
                                            MinipoolDeposit depositType = MinipoolDeposit.None;
                                            uint256 count = 0;
                                            uint256 minipoolCapacity = 0;
                                            for (uint256 i = 0; i < maxAssignments; ++i) {
                                                // Optimised for multiple of the same deposit type
                                                if (count == 0) {
                                                    (depositType, count) = _rocketMinipoolQueue.getNextDepositLegacy();
                                                    if (depositType == MinipoolDeposit.None) { break; }
                                                    minipoolCapacity = rocketDAOProtocolSettingsMinipool.getDepositUserAmount(depositType);
                                                }
                                                count--;
                                                if (minipoolCapacity == 0 || balance.sub(totalEther) < minipoolCapacity) { break; }
                                                // Dequeue the minipool
                                                address minipoolAddress = _rocketMinipoolQueue.dequeueMinipoolByDepositLegacy(depositType);
                                                // Update running total
                                                totalEther = totalEther.add(minipoolCapacity);
                                                // Add assignment
                                                assignments[i].etherAssigned = minipoolCapacity;
                                                assignments[i].minipoolAddress = minipoolAddress;
                                            }
                                            if (totalEther > 0) {
                                                // Withdraw ETH from vault
                                                rocketVault.withdrawEther(totalEther);
                                                // Perform assignments
                                                for (uint256 i = 0; i < maxAssignments; ++i) {
                                                    if (assignments[i].etherAssigned == 0) { break; }
                                                    RocketMinipoolInterface minipool = RocketMinipoolInterface(assignments[i].minipoolAddress);
                                                    // Assign deposit to minipool
                                                    minipool.userDeposit{value: assignments[i].etherAssigned}();
                                                    // Emit deposit assigned event
                                                    emit DepositAssigned(assignments[i].minipoolAddress, assignments[i].etherAssigned, block.timestamp);
                                                }
                                            }
                                            return true;
                                        }
                                        /// @dev Withdraw excess deposit pool balance for rETH collateral
                                        /// @param _amount The amount of excess ETH to withdraw
                                        function withdrawExcessBalance(uint256 _amount) override external onlyThisLatestContract onlyLatestContract("rocketTokenRETH", msg.sender) {
                                            // Check amount
                                            require(_amount <= getExcessBalance(), "Insufficient excess balance for withdrawal");
                                            // Withdraw ETH from vault
                                            rocketVault.withdrawEther(_amount);
                                            // Transfer to rETH contract
                                            rocketTokenRETH.depositExcess{value: _amount}();
                                            // Emit excess withdrawn event
                                            emit ExcessWithdrawn(msg.sender, _amount, block.timestamp);
                                        }
                                    }
                                    

                                    File 2 of 9: RocketTokenRETH
                                    // 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;
                                    /**
                                     * @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 "@openzeppelin/contracts/token/ERC20/ERC20.sol";
                                    import "../RocketBase.sol";
                                    import "../../interface/deposit/RocketDepositPoolInterface.sol";
                                    import "../../interface/network/RocketNetworkBalancesInterface.sol";
                                    import "../../interface/token/RocketTokenRETHInterface.sol";
                                    import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNetworkInterface.sol";
                                    // rETH is a tokenised stake in the Rocket Pool network
                                    // rETH is backed by ETH (subject to liquidity) at a variable exchange rate
                                    contract RocketTokenRETH is RocketBase, ERC20, RocketTokenRETHInterface {
                                        // Libs
                                        using SafeMath for uint;
                                        // Events
                                        event EtherDeposited(address indexed from, uint256 amount, uint256 time);
                                        event TokensMinted(address indexed to, uint256 amount, uint256 ethAmount, uint256 time);
                                        event TokensBurned(address indexed from, uint256 amount, uint256 ethAmount, uint256 time);
                                        // Construct with our token details
                                        constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) ERC20("Rocket Pool ETH", "rETH") {
                                            // Version
                                            version = 1;
                                        }
                                        // Receive an ETH deposit from a minipool or generous individual
                                        receive() external payable {
                                            // Emit ether deposited event
                                            emit EtherDeposited(msg.sender, msg.value, block.timestamp);
                                        }
                                        // Calculate the amount of ETH backing an amount of rETH
                                        function getEthValue(uint256 _rethAmount) override public view returns (uint256) {
                                            // Get network balances
                                            RocketNetworkBalancesInterface rocketNetworkBalances = RocketNetworkBalancesInterface(getContractAddress("rocketNetworkBalances"));
                                            uint256 totalEthBalance = rocketNetworkBalances.getTotalETHBalance();
                                            uint256 rethSupply = rocketNetworkBalances.getTotalRETHSupply();
                                            // Use 1:1 ratio if no rETH is minted
                                            if (rethSupply == 0) { return _rethAmount; }
                                            // Calculate and return
                                            return _rethAmount.mul(totalEthBalance).div(rethSupply);
                                        }
                                        // Calculate the amount of rETH backed by an amount of ETH
                                        function getRethValue(uint256 _ethAmount) override public view returns (uint256) {
                                            // Get network balances
                                            RocketNetworkBalancesInterface rocketNetworkBalances = RocketNetworkBalancesInterface(getContractAddress("rocketNetworkBalances"));
                                            uint256 totalEthBalance = rocketNetworkBalances.getTotalETHBalance();
                                            uint256 rethSupply = rocketNetworkBalances.getTotalRETHSupply();
                                            // Use 1:1 ratio if no rETH is minted
                                            if (rethSupply == 0) { return _ethAmount; }
                                            // Check network ETH balance
                                            require(totalEthBalance > 0, "Cannot calculate rETH token amount while total network balance is zero");
                                            // Calculate and return
                                            return _ethAmount.mul(rethSupply).div(totalEthBalance);
                                        }
                                        // Get the current ETH : rETH exchange rate
                                        // Returns the amount of ETH backing 1 rETH
                                        function getExchangeRate() override external view returns (uint256) {
                                            return getEthValue(1 ether);
                                        }
                                        // Get the total amount of collateral available
                                        // Includes rETH contract balance & excess deposit pool balance
                                        function getTotalCollateral() override public view returns (uint256) {
                                            RocketDepositPoolInterface rocketDepositPool = RocketDepositPoolInterface(getContractAddress("rocketDepositPool"));
                                            return rocketDepositPool.getExcessBalance().add(address(this).balance);
                                        }
                                        // Get the current ETH collateral rate
                                        // Returns the portion of rETH backed by ETH in the contract as a fraction of 1 ether
                                        function getCollateralRate() override public view returns (uint256) {
                                            uint256 totalEthValue = getEthValue(totalSupply());
                                            if (totalEthValue == 0) { return calcBase; }
                                            return calcBase.mul(address(this).balance).div(totalEthValue);
                                        }
                                        // Deposit excess ETH from deposit pool
                                        // Only accepts calls from the RocketDepositPool contract
                                        function depositExcess() override external payable onlyLatestContract("rocketDepositPool", msg.sender) {
                                            // Emit ether deposited event
                                            emit EtherDeposited(msg.sender, msg.value, block.timestamp);
                                        }
                                        // Mint rETH
                                        // Only accepts calls from the RocketDepositPool contract
                                        function mint(uint256 _ethAmount, address _to) override external onlyLatestContract("rocketDepositPool", msg.sender) {
                                            // Get rETH amount
                                            uint256 rethAmount = getRethValue(_ethAmount);
                                            // Check rETH amount
                                            require(rethAmount > 0, "Invalid token mint amount");
                                            // Update balance & supply
                                            _mint(_to, rethAmount);
                                            // Emit tokens minted event
                                            emit TokensMinted(_to, rethAmount, _ethAmount, block.timestamp);
                                        }
                                        // Burn rETH for ETH
                                        function burn(uint256 _rethAmount) override external {
                                            // Check rETH amount
                                            require(_rethAmount > 0, "Invalid token burn amount");
                                            require(balanceOf(msg.sender) >= _rethAmount, "Insufficient rETH balance");
                                            // Get ETH amount
                                            uint256 ethAmount = getEthValue(_rethAmount);
                                            // Get & check ETH balance
                                            uint256 ethBalance = getTotalCollateral();
                                            require(ethBalance >= ethAmount, "Insufficient ETH balance for exchange");
                                            // Update balance & supply
                                            _burn(msg.sender, _rethAmount);
                                            // Withdraw ETH from deposit pool if required
                                            withdrawDepositCollateral(ethAmount);
                                            // Transfer ETH to sender
                                            msg.sender.transfer(ethAmount);
                                            // Emit tokens burned event
                                            emit TokensBurned(msg.sender, _rethAmount, ethAmount, block.timestamp);
                                        }
                                        // Withdraw ETH from the deposit pool for collateral if required
                                        function withdrawDepositCollateral(uint256 _ethRequired) private {
                                            // Check rETH contract balance
                                            uint256 ethBalance = address(this).balance;
                                            if (ethBalance >= _ethRequired) { return; }
                                            // Withdraw
                                            RocketDepositPoolInterface rocketDepositPool = RocketDepositPoolInterface(getContractAddress("rocketDepositPool"));
                                            rocketDepositPool.withdrawExcessBalance(_ethRequired.sub(ethBalance));
                                        }
                                        // Sends any excess ETH from this contract to the deposit pool (as determined by target collateral rate)
                                        function depositExcessCollateral() external override {
                                            // Load contracts
                                            RocketDAOProtocolSettingsNetworkInterface rocketDAOProtocolSettingsNetwork = RocketDAOProtocolSettingsNetworkInterface(getContractAddress("rocketDAOProtocolSettingsNetwork"));
                                            RocketDepositPoolInterface rocketDepositPool = RocketDepositPoolInterface(getContractAddress("rocketDepositPool"));
                                            // Get collateral and target collateral rate
                                            uint256 collateralRate = getCollateralRate();
                                            uint256 targetCollateralRate = rocketDAOProtocolSettingsNetwork.getTargetRethCollateralRate();
                                            // Check if we are in excess
                                            if (collateralRate > targetCollateralRate) {
                                                // Calculate our target collateral in ETH
                                                uint256 targetCollateral = address(this).balance.mul(targetCollateralRate).div(collateralRate);
                                                // If we have excess
                                                if (address(this).balance > targetCollateral) {
                                                    // Send that excess to deposit pool
                                                    uint256 excessCollateral = address(this).balance.sub(targetCollateral);
                                                    rocketDepositPool.recycleExcessCollateral{value: excessCollateral}();
                                                }
                                            }
                                        }
                                        // This is called by the base ERC20 contract before all transfer, mint, and burns
                                        function _beforeTokenTransfer(address from, address, uint256) internal override {
                                            // Don't run check if this is a mint transaction
                                            if (from != address(0)) {
                                                // Check which block the user's last deposit was
                                                bytes32 key = keccak256(abi.encodePacked("user.deposit.block", from));
                                                uint256 lastDepositBlock = getUint(key);
                                                if (lastDepositBlock > 0) {
                                                    // Ensure enough blocks have passed
                                                    uint256 depositDelay = getUint(keccak256(abi.encodePacked(keccak256("dao.protocol.setting.network"), "network.reth.deposit.delay")));
                                                    uint256 blocksPassed = block.number.sub(lastDepositBlock);
                                                    require(blocksPassed > depositDelay, "Not enough time has passed since deposit");
                                                    // Clear the state as it's no longer necessary to check this until another deposit is made
                                                    deleteUint(key);
                                                }
                                            }
                                        }
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |    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 RocketDAOProtocolSettingsNetworkInterface {
                                        function getNodeConsensusThreshold() external view returns (uint256);
                                        function getSubmitBalancesEnabled() external view returns (bool);
                                        function getSubmitBalancesFrequency() external view returns (uint256);
                                        function getSubmitPricesEnabled() external view returns (bool);
                                        function getSubmitPricesFrequency() external view returns (uint256);
                                        function getMinimumNodeFee() external view returns (uint256);
                                        function getTargetNodeFee() external view returns (uint256);
                                        function getMaximumNodeFee() external view returns (uint256);
                                        function getNodeFeeDemandRange() external view returns (uint256);
                                        function getTargetRethCollateralRate() external view returns (uint256);
                                        function getRethDepositDelay() 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 RocketDepositPoolInterface {
                                        function getBalance() external view returns (uint256);
                                        function getExcessBalance() external view returns (uint256);
                                        function deposit() external payable;
                                        function recycleDissolvedDeposit() external payable;
                                        function recycleExcessCollateral() external payable;
                                        function recycleLiquidatedStake() external payable;
                                        function assignDeposits() external;
                                        function withdrawExcessBalance(uint256 _amount) external;
                                        function getUserLastDepositBlock(address _address) 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 RocketNetworkBalancesInterface {
                                        function getBalancesBlock() external view returns (uint256);
                                        function getLatestReportableBlock() external view returns (uint256);
                                        function getTotalETHBalance() external view returns (uint256);
                                        function getStakingETHBalance() external view returns (uint256);
                                        function getTotalRETHSupply() external view returns (uint256);
                                        function getETHUtilizationRate() external view returns (uint256);
                                        function submitBalances(uint256 _block, uint256 _total, uint256 _staking, uint256 _rethSupply) external;
                                        function executeUpdateBalances(uint256 _block, uint256 _totalEth, uint256 _stakingEth, uint256 _rethSupply) 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 RocketTokenRETHInterface is IERC20 {
                                        function getEthValue(uint256 _rethAmount) external view returns (uint256);
                                        function getRethValue(uint256 _ethAmount) external view returns (uint256);
                                        function getExchangeRate() external view returns (uint256);
                                        function getTotalCollateral() external view returns (uint256);
                                        function getCollateralRate() external view returns (uint256);
                                        function depositExcess() external payable;
                                        function depositExcessCollateral() external;
                                        function mint(uint256 _ethAmount, address _to) external;
                                        function burn(uint256 _rethAmount) external;
                                    }
                                    

                                    File 3 of 9: RocketVault
                                    // 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;
                                    import "./IERC20.sol";
                                    import "../../math/SafeMath.sol";
                                    import "../../utils/Address.sol";
                                    /**
                                     * @title SafeERC20
                                     * @dev Wrappers around ERC20 operations that throw on failure (when the token
                                     * contract returns false). Tokens that return no value (and instead revert or
                                     * throw on failure) are also supported, non-reverting calls are assumed to be
                                     * successful.
                                     * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
                                     * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
                                     */
                                    library SafeERC20 {
                                        using SafeMath for uint256;
                                        using Address for address;
                                        function safeTransfer(IERC20 token, address to, uint256 value) internal {
                                            _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
                                        }
                                        function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
                                            _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
                                        }
                                        /**
                                         * @dev Deprecated. This function has issues similar to the ones found in
                                         * {IERC20-approve}, and its usage is discouraged.
                                         *
                                         * Whenever possible, use {safeIncreaseAllowance} and
                                         * {safeDecreaseAllowance} instead.
                                         */
                                        function safeApprove(IERC20 token, address spender, uint256 value) internal {
                                            // safeApprove should only be called when setting an initial allowance,
                                            // or when resetting it to zero. To increase and decrease it, use
                                            // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                                            // solhint-disable-next-line max-line-length
                                            require((value == 0) || (token.allowance(address(this), spender) == 0),
                                                "SafeERC20: approve from non-zero to non-zero allowance"
                                            );
                                            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
                                        }
                                        function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                            uint256 newAllowance = token.allowance(address(this), spender).add(value);
                                            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
                                        }
                                        function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                            uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
                                            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
                                        }
                                        /**
                                         * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
                                         * on the return value: the return value is optional (but if data is returned, it must not be false).
                                         * @param token The token targeted by the call.
                                         * @param data The call data (encoded using abi.encode or one of its variants).
                                         */
                                        function _callOptionalReturn(IERC20 token, bytes memory data) private {
                                            // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
                                            // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
                                            // the target address contains contract code and also asserts for success in the low-level call.
                                            bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
                                            if (returndata.length > 0) { // Return data is optional
                                                // solhint-disable-next-line max-line-length
                                                require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
                                            }
                                        }
                                    }
                                    // SPDX-License-Identifier: MIT
                                    pragma solidity >=0.6.2 <0.8.0;
                                    /**
                                     * @dev Collection of functions related to the address type
                                     */
                                    library Address {
                                        /**
                                         * @dev Returns true if `account` is a contract.
                                         *
                                         * [IMPORTANT]
                                         * ====
                                         * It is unsafe to assume that an address for which this function returns
                                         * false is an externally-owned account (EOA) and not a contract.
                                         *
                                         * Among others, `isContract` will return false for the following
                                         * types of addresses:
                                         *
                                         *  - an externally-owned account
                                         *  - a contract in construction
                                         *  - an address where a contract will be created
                                         *  - an address where a contract lived, but was destroyed
                                         * ====
                                         */
                                        function isContract(address account) internal view returns (bool) {
                                            // This method relies on extcodesize, which returns 0 for contracts in
                                            // construction, since the code is only stored at the end of the
                                            // constructor execution.
                                            uint256 size;
                                            // solhint-disable-next-line no-inline-assembly
                                            assembly { size := extcodesize(account) }
                                            return size > 0;
                                        }
                                        /**
                                         * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
                                         * `recipient`, forwarding all available gas and reverting on errors.
                                         *
                                         * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
                                         * of certain opcodes, possibly making contracts go over the 2300 gas limit
                                         * imposed by `transfer`, making them unable to receive funds via
                                         * `transfer`. {sendValue} removes this limitation.
                                         *
                                         * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
                                         *
                                         * IMPORTANT: because control is transferred to `recipient`, care must be
                                         * taken to not create reentrancy vulnerabilities. Consider using
                                         * {ReentrancyGuard} or the
                                         * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
                                         */
                                        function sendValue(address payable recipient, uint256 amount) internal {
                                            require(address(this).balance >= amount, "Address: insufficient balance");
                                            // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
                                            (bool success, ) = recipient.call{ value: amount }("");
                                            require(success, "Address: unable to send value, recipient may have reverted");
                                        }
                                        /**
                                         * @dev Performs a Solidity function call using a low level `call`. A
                                         * plain`call` is an unsafe replacement for a function call: use this
                                         * function instead.
                                         *
                                         * If `target` reverts with a revert reason, it is bubbled up by this
                                         * function (like regular Solidity function calls).
                                         *
                                         * Returns the raw returned data. To convert to the expected return value,
                                         * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
                                         *
                                         * Requirements:
                                         *
                                         * - `target` must be a contract.
                                         * - calling `target` with `data` must not revert.
                                         *
                                         * _Available since v3.1._
                                         */
                                        function functionCall(address target, bytes memory data) internal returns (bytes memory) {
                                          return functionCall(target, data, "Address: low-level call failed");
                                        }
                                        /**
                                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
                                         * `errorMessage` as a fallback revert reason when `target` reverts.
                                         *
                                         * _Available since v3.1._
                                         */
                                        function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                                            return functionCallWithValue(target, data, 0, errorMessage);
                                        }
                                        /**
                                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                                         * but also transferring `value` wei to `target`.
                                         *
                                         * Requirements:
                                         *
                                         * - the calling contract must have an ETH balance of at least `value`.
                                         * - the called Solidity function must be `payable`.
                                         *
                                         * _Available since v3.1._
                                         */
                                        function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
                                            return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
                                        }
                                        /**
                                         * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
                                         * with `errorMessage` as a fallback revert reason when `target` reverts.
                                         *
                                         * _Available since v3.1._
                                         */
                                        function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
                                            require(address(this).balance >= value, "Address: insufficient balance for call");
                                            require(isContract(target), "Address: call to non-contract");
                                            // solhint-disable-next-line avoid-low-level-calls
                                            (bool success, bytes memory returndata) = target.call{ value: value }(data);
                                            return _verifyCallResult(success, returndata, errorMessage);
                                        }
                                        /**
                                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                                         * but performing a static call.
                                         *
                                         * _Available since v3.3._
                                         */
                                        function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
                                            return functionStaticCall(target, data, "Address: low-level static call failed");
                                        }
                                        /**
                                         * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                                         * but performing a static call.
                                         *
                                         * _Available since v3.3._
                                         */
                                        function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
                                            require(isContract(target), "Address: static call to non-contract");
                                            // solhint-disable-next-line avoid-low-level-calls
                                            (bool success, bytes memory returndata) = target.staticcall(data);
                                            return _verifyCallResult(success, returndata, errorMessage);
                                        }
                                        /**
                                         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
                                         * but performing a delegate call.
                                         *
                                         * _Available since v3.4._
                                         */
                                        function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
                                            return functionDelegateCall(target, data, "Address: low-level delegate call failed");
                                        }
                                        /**
                                         * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
                                         * but performing a delegate call.
                                         *
                                         * _Available since v3.4._
                                         */
                                        function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
                                            require(isContract(target), "Address: delegate call to non-contract");
                                            // solhint-disable-next-line avoid-low-level-calls
                                            (bool success, bytes memory returndata) = target.delegatecall(data);
                                            return _verifyCallResult(success, returndata, errorMessage);
                                        }
                                        function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
                                            if (success) {
                                                return returndata;
                                            } else {
                                                // Look for revert reason and bubble it up if present
                                                if (returndata.length > 0) {
                                                    // The easiest way to bubble the revert reason is using memory via assembly
                                                    // solhint-disable-next-line no-inline-assembly
                                                    assembly {
                                                        let returndata_size := mload(returndata)
                                                        revert(add(32, returndata), returndata_size)
                                                    }
                                                } else {
                                                    revert(errorMessage);
                                                }
                                            }
                                        }
                                    }
                                    // 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/RocketVaultInterface.sol";
                                    import "../interface/RocketVaultWithdrawerInterface.sol";
                                    import "@openzeppelin/contracts/math/SafeMath.sol";
                                    import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
                                    import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
                                    // ETH and rETH are stored here to prevent contract upgrades from affecting balances
                                    // The RocketVault contract must not be upgraded
                                    contract RocketVault is RocketBase, RocketVaultInterface {
                                        // Libs
                                        using SafeMath for uint;
                                        using SafeERC20 for IERC20;
                                        // Network contract balances
                                        mapping(string => uint256) etherBalances;
                                        mapping(bytes32 => uint256) tokenBalances;
                                        // Events
                                        event EtherDeposited(string indexed by, uint256 amount, uint256 time);
                                        event EtherWithdrawn(string indexed by, uint256 amount, uint256 time);
                                        event TokenDeposited(bytes32 indexed by, address indexed tokenAddress, uint256 amount, uint256 time);
                                        event TokenWithdrawn(bytes32 indexed by, address indexed tokenAddress, uint256 amount, uint256 time);
                                        event TokenBurned(bytes32 indexed by, address indexed tokenAddress, uint256 amount, uint256 time);
                                        event TokenTransfer(bytes32 indexed by, bytes32 indexed to, address indexed tokenAddress, uint256 amount, uint256 time);
                                    \t// Construct
                                        constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
                                            version = 1;
                                        }
                                        // Get a contract's ETH balance by address
                                        function balanceOf(string memory _networkContractName) override external view returns (uint256) {
                                            // Return balance
                                            return etherBalances[_networkContractName];
                                        }
                                        // Get the balance of a token held by a network contract
                                        function balanceOfToken(string memory _networkContractName, IERC20 _tokenAddress) override external view returns (uint256) {
                                            // Return balance
                                            return tokenBalances[keccak256(abi.encodePacked(_networkContractName, _tokenAddress))];
                                        }
                                        // Accept an ETH deposit from a network contract
                                        // Only accepts calls from Rocket Pool network contracts
                                        function depositEther() override external payable onlyLatestNetworkContract {
                                            // Valid amount?
                                            require(msg.value > 0, "No valid amount of ETH given to deposit");
                                            // Get contract key
                                            string memory contractName = getContractName(msg.sender);
                                            // Update contract balance
                                            etherBalances[contractName] = etherBalances[contractName].add(msg.value);
                                            // Emit ether deposited event
                                            emit EtherDeposited(contractName, msg.value, block.timestamp);
                                        }
                                        // Withdraw an amount of ETH to a network contract
                                        // Only accepts calls from Rocket Pool network contracts
                                        function withdrawEther(uint256 _amount) override external onlyLatestNetworkContract {
                                            // Valid amount?
                                            require(_amount > 0, "No valid amount of ETH given to withdraw");
                                            // Get contract key
                                            string memory contractName = getContractName(msg.sender);
                                            // Check and update contract balance
                                            require(etherBalances[contractName] >= _amount, "Insufficient contract ETH balance");
                                            etherBalances[contractName] = etherBalances[contractName].sub(_amount);
                                            // Withdraw
                                            RocketVaultWithdrawerInterface withdrawer = RocketVaultWithdrawerInterface(msg.sender);
                                            withdrawer.receiveVaultWithdrawalETH{value: _amount}();
                                            // Emit ether withdrawn event
                                            emit EtherWithdrawn(contractName, _amount, block.timestamp);
                                        }
                                        // Accept an token deposit and assign its balance to a network contract (saves a large amount of gas this way through not needing a double token transfer via a network contract first)
                                        function depositToken(string memory _networkContractName, IERC20 _tokenContract, uint256 _amount) override external {
                                             // Valid amount?
                                            require(_amount > 0, "No valid amount of tokens given to deposit");
                                            // Make sure the network contract is valid (will throw if not)
                                            require(getContractAddress(_networkContractName) != address(0x0), "Not a valid network contract");
                                            // Get contract key
                                            bytes32 contractKey = keccak256(abi.encodePacked(_networkContractName, address(_tokenContract)));
                                            // Send the tokens to this contract now
                                            require(_tokenContract.transferFrom(msg.sender, address(this), _amount), "Token transfer was not successful");
                                            // Update contract balance
                                            tokenBalances[contractKey] = tokenBalances[contractKey].add(_amount);
                                            // Emit token transfer
                                            emit TokenDeposited(contractKey, address(_tokenContract), _amount, block.timestamp);
                                        }
                                        // Withdraw an amount of a ERC20 token to an address
                                        // Only accepts calls from Rocket Pool network contracts
                                        function withdrawToken(address _withdrawalAddress, IERC20 _tokenAddress, uint256 _amount) override external onlyLatestNetworkContract {
                                            // Valid amount?
                                            require(_amount > 0, "No valid amount of tokens given to withdraw");
                                            // Get contract key
                                            bytes32 contractKey = keccak256(abi.encodePacked(getContractName(msg.sender), _tokenAddress));
                                            // Update balances
                                            tokenBalances[contractKey] = tokenBalances[contractKey].sub(_amount);
                                            // Get the token ERC20 instance
                                            IERC20 tokenContract = IERC20(_tokenAddress);
                                            // Withdraw to the desired address
                                            require(tokenContract.transfer(_withdrawalAddress, _amount), "Rocket Vault token withdrawal unsuccessful");
                                            // Emit token withdrawn event
                                            emit TokenWithdrawn(contractKey, address(_tokenAddress), _amount, block.timestamp);
                                        }
                                        // Transfer token from one contract to another
                                        // Only accepts calls from Rocket Pool network contracts
                                        function transferToken(string memory _networkContractName, IERC20 _tokenAddress, uint256 _amount) override external onlyLatestNetworkContract {
                                            // Valid amount?
                                            require(_amount > 0, "No valid amount of tokens given to transfer");
                                            // Make sure the network contract is valid (will throw if not)
                                            require(getContractAddress(_networkContractName) != address(0x0), "Not a valid network contract");
                                            // Get contract keys
                                            bytes32 contractKeyFrom = keccak256(abi.encodePacked(getContractName(msg.sender), _tokenAddress));
                                            bytes32 contractKeyTo = keccak256(abi.encodePacked(_networkContractName, _tokenAddress));
                                            // Update balances
                                            tokenBalances[contractKeyFrom] = tokenBalances[contractKeyFrom].sub(_amount);
                                            tokenBalances[contractKeyTo] = tokenBalances[contractKeyTo].add(_amount);
                                            // Emit token withdrawn event
                                            emit TokenTransfer(contractKeyFrom, contractKeyTo, address(_tokenAddress), _amount, block.timestamp);
                                        }
                                        // Burns an amount of a token that implements a burn(uint256) method
                                        // Only accepts calls from Rocket Pool network contracts
                                        function burnToken(ERC20Burnable _tokenAddress, uint256 _amount) override external onlyLatestNetworkContract {
                                            // Get contract key
                                            bytes32 contractKey = keccak256(abi.encodePacked(getContractName(msg.sender), _tokenAddress));
                                            // Update balances
                                            tokenBalances[contractKey] = tokenBalances[contractKey].sub(_amount);
                                            // Get the token ERC20 instance
                                            ERC20Burnable tokenContract = ERC20Burnable(_tokenAddress);
                                            // Burn the tokens
                                            tokenContract.burn(_amount);
                                            // Emit token burn event
                                            emit TokenBurned(contractKey, address(_tokenAddress), _amount, 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 RocketVaultWithdrawerInterface {
                                        function receiveVaultWithdrawalETH() external payable; 
                                    }
                                    

                                    File 4 of 9: 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 5 of 9: RocketDAOProtocolSettingsDeposit
                                    /**
                                       *       .
                                       *      / \\
                                       *     |.'.|
                                       *     |'.'|
                                       *   ,'|   |'.
                                       *  |,-'-|-'-.|
                                       *   __|_| |         _        _      _____           _
                                       *  | ___ \\|        | |      | |    | ___ \\         | |
                                       *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                       *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                       *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                       *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                       * +---------------------------------------------------+
                                       * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    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    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // 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(address(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, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // 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, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    pragma solidity >0.5.0 <0.9.0;
                                    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, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    interface RocketDAOProtocolSettingsDepositInterface {
                                        function getDepositEnabled() external view returns (bool);
                                        function getAssignDepositsEnabled() external view returns (bool);
                                        function getMinimumDeposit() external view returns (uint256);
                                        function getMaximumDepositPoolSize() external view returns (uint256);
                                        function getMaximumDepositAssignments() external view returns (uint256);
                                        function getMaximumDepositSocialisedAssignments() external view returns (uint256);
                                        function getDepositFee() 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, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    pragma solidity 0.8.18;
                                    import "./RocketDAOProtocolSettings.sol";
                                    import "../../../../interface/dao/protocol/settings/RocketDAOProtocolSettingsDepositInterface.sol";
                                     
                                    /// @notice Network deposit settings
                                    contract RocketDAOProtocolSettingsDeposit is RocketDAOProtocolSettings, RocketDAOProtocolSettingsDepositInterface {
                                        constructor(RocketStorageInterface _rocketStorageAddress) RocketDAOProtocolSettings(_rocketStorageAddress, "deposit") {
                                            version = 4;
                                            // Initialize settings on deployment
                                            if(!getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")))) {
                                                // Apply settings
                                                setSettingBool("deposit.enabled", false);
                                                setSettingBool("deposit.assign.enabled", true);
                                                setSettingUint("deposit.minimum", 0.01 ether);
                                                setSettingUint("deposit.pool.maximum", 160 ether);
                                                setSettingUint("deposit.assign.maximum", 90);
                                                setSettingUint("deposit.assign.socialised.maximum", 2);
                                                setSettingUint("deposit.fee", 0.0005 ether);    // Set to approx. 1 day of rewards at 18.25% APR
                                                // Settings initialised
                                                setBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")), true);
                                            }
                                        }
                                        /// @notice Update a setting, overrides inherited setting method with extra checks for this contract
                                        /// @param _settingPath The path of the setting within this contract's namespace
                                        /// @param _value The value to set it to
                                        function setSettingUint(string memory _settingPath, uint256 _value) override public onlyDAOProtocolProposal {
                                            // Some safety guards for certain settings
                                            if(getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")))) {
                                                if(keccak256(abi.encodePacked(_settingPath)) == keccak256(abi.encodePacked("deposit.fee"))) {
                                                    require(_value < 0.01 ether, "Fee must be less than 1%");
                                                }
                                            }
                                            // Update setting now
                                            setUint(keccak256(abi.encodePacked(settingNameSpace, _settingPath)), _value);
                                        }
                                        /// @notice Returns true if deposits are currently enabled
                                        function getDepositEnabled() override external view returns (bool) {
                                            return getSettingBool("deposit.enabled");
                                        }
                                        /// @notice Returns true if deposit assignments are currently enabled
                                        function getAssignDepositsEnabled() override external view returns (bool) {
                                            return getSettingBool("deposit.assign.enabled");
                                        }
                                        /// @notice Returns the minimum deposit size
                                        function getMinimumDeposit() override external view returns (uint256) {
                                            return getSettingUint("deposit.minimum");
                                        }
                                        /// @notice Returns the maximum size of the deposit pool
                                        function getMaximumDepositPoolSize() override external view returns (uint256) {
                                            return getSettingUint("deposit.pool.maximum");
                                        }
                                        /// @notice Returns the maximum number of deposit assignments to perform at once
                                        function getMaximumDepositAssignments() override external view returns (uint256) {
                                            return getSettingUint("deposit.assign.maximum");
                                        }
                                        /// @notice Returns the maximum number of socialised (ie, not related to deposit size) assignments to perform
                                        function getMaximumDepositSocialisedAssignments() override external view returns (uint256) {
                                            return getSettingUint("deposit.assign.socialised.maximum");
                                        }
                                        /// @notice Returns the current fee paid on user deposits
                                        function getDepositFee() override external view returns (uint256) {
                                            return getSettingUint("deposit.fee");
                                        }
                                    }
                                    

                                    File 6 of 9: RocketNetworkBalances
                                    /**
                                       *       .
                                       *      / \\
                                       *     |.'.|
                                       *     |'.'|
                                       *   ,'|   |'.
                                       *  |,-'-|-'-.|
                                       *   __|_| |         _        _      _____           _
                                       *  | ___ \\|        | |      | |    | ___ \\         | |
                                       *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                       *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                       *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                       *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                       * +---------------------------------------------------+
                                       * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    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    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // 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(address(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, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    interface RocketDAONodeTrustedInterface {
                                        function getBootstrapModeDisabled() external view returns (bool);
                                        function getMemberQuorumVotesRequired() external view returns (uint256);
                                        function getMemberAt(uint256 _index) external view returns (address);
                                        function getMemberCount() external view returns (uint256);
                                        function getMemberMinRequired() external view returns (uint256);
                                        function getMemberIsValid(address _nodeAddress) external view returns (bool);
                                        function getMemberLastProposalTime(address _nodeAddress) external view returns (uint256);
                                        function getMemberID(address _nodeAddress) external view returns (string memory);
                                        function getMemberUrl(address _nodeAddress) external view returns (string memory);
                                        function getMemberJoinedTime(address _nodeAddress) external view returns (uint256);
                                        function getMemberProposalExecutedTime(string memory _proposalType, address _nodeAddress) external view returns (uint256);
                                        function getMemberRPLBondAmount(address _nodeAddress) external view returns (uint256);
                                        function getMemberIsChallenged(address _nodeAddress) external view returns (bool);
                                        function getMemberUnbondedValidatorCount(address _nodeAddress) external view returns (uint256);
                                        function incrementMemberUnbondedValidatorCount(address _nodeAddress) external;
                                        function decrementMemberUnbondedValidatorCount(address _nodeAddress) external;
                                        function bootstrapMember(string memory _id, string memory _url, address _nodeAddress) external;
                                        function bootstrapSettingUint(string memory _settingContractName, string memory _settingPath, uint256 _value) external;
                                        function bootstrapSettingBool(string memory _settingContractName, string memory _settingPath, bool _value) external;
                                        function bootstrapUpgrade(string memory _type, string memory _name, string memory _contractAbi, address _contractAddress) external;
                                        function bootstrapDisable(bool _confirmDisableBootstrapMode) external;
                                        function memberJoinRequired(string memory _id, string memory _url) external;
                                    }
                                    /**
                                       *       .
                                       *      / \\
                                       *     |.'.|
                                       *     |'.'|
                                       *   ,'|   |'.
                                       *  |,-'-|-'-.|
                                       *   __|_| |         _        _      _____           _
                                       *  | ___ \\|        | |      | |    | ___ \\         | |
                                       *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                       *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                       *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                       *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                       * +---------------------------------------------------+
                                       * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    pragma abicoder v2;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    interface RocketNetworkBalancesInterface {
                                        function getBalancesBlock() external view returns (uint256);
                                        function getTotalETHBalance() external view returns (uint256);
                                        function getStakingETHBalance() external view returns (uint256);
                                        function getTotalRETHSupply() external view returns (uint256);
                                        function getETHUtilizationRate() external view returns (uint256);
                                        function submitBalances(uint256 _block, uint256 _slotTimestamp, uint256 _total, uint256 _staking, uint256 _rethSupply) external;
                                        function executeUpdateBalances(uint256 _block, uint256 _slotTimestamp, uint256 _totalEth, uint256 _stakingEth, uint256 _rethSupply) external;
                                    }
                                    /**
                                       *       .
                                       *      / \\
                                       *     |.'.|
                                       *     |'.'|
                                       *   ,'|   |'.
                                       *  |,-'-|-'-.|
                                       *   __|_| |         _        _      _____           _
                                       *  | ___ \\|        | |      | |    | ___ \\         | |
                                       *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                       *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                       *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                       *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                       * +---------------------------------------------------+
                                       * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    interface RocketDAOProtocolSettingsNetworkInterface {
                                        function getNodeConsensusThreshold() external view returns (uint256);
                                        function getNodePenaltyThreshold() external view returns (uint256);
                                        function getPerPenaltyRate() external view returns (uint256);
                                        function getSubmitBalancesEnabled() external view returns (bool);
                                        function getSubmitBalancesFrequency() external view returns (uint256);
                                        function getSubmitPricesEnabled() external view returns (bool);
                                        function getSubmitPricesFrequency() external view returns (uint256);
                                        function getMinimumNodeFee() external view returns (uint256);
                                        function getTargetNodeFee() external view returns (uint256);
                                        function getMaximumNodeFee() external view returns (uint256);
                                        function getNodeFeeDemandRange() external view returns (uint256);
                                        function getTargetRethCollateralRate() external view returns (uint256);
                                        function getRethDepositDelay() external view returns (uint256);
                                        function getSubmitRewardsEnabled() external view returns (bool);
                                    }
                                    /**
                                       *       .
                                       *      / \\
                                       *     |.'.|
                                       *     |'.'|
                                       *   ,'|   |'.
                                       *  |,-'-|-'-.|
                                       *   __|_| |         _        _      _____           _
                                       *  | ___ \\|        | |      | |    | ___ \\         | |
                                       *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                       *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                       *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                       *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                       * +---------------------------------------------------+
                                       * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    pragma solidity 0.8.18;
                                    pragma abicoder v2;
                                    import "../RocketBase.sol";
                                    import "../../interface/dao/node/RocketDAONodeTrustedInterface.sol";
                                    import "../../interface/network/RocketNetworkBalancesInterface.sol";
                                    import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNetworkInterface.sol";
                                    /// @notice Oracle contract for network balance data
                                    contract RocketNetworkBalances is RocketBase, RocketNetworkBalancesInterface {
                                        // Events
                                        event BalancesSubmitted(address indexed from, uint256 block, uint256 slotTimestamp, uint256 totalEth, uint256 stakingEth, uint256 rethSupply, uint256 blockTimestamp);
                                        event BalancesUpdated(uint256 indexed block, uint256 slotTimestamp, uint256 totalEth, uint256 stakingEth, uint256 rethSupply, uint256 blockTimestamp);
                                        constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
                                            version = 3;
                                        }
                                        /// @notice The block number which balances are current for
                                        function getBalancesBlock() override public view returns (uint256) {
                                            return getUint(keccak256("network.balances.updated.block"));
                                        }
                                        /// @notice Sets the block number which balances are current for
                                        function setBalancesBlock(uint256 _value) private {
                                            setUint(keccak256("network.balances.updated.block"), _value);
                                        }
                                        /// @notice The current RP network total ETH balance
                                        function getTotalETHBalance() override public view returns (uint256) {
                                            return getUint(keccak256("network.balance.total"));
                                        }
                                        /// @notice Sets the current RP network total ETH balance
                                        function setTotalETHBalance(uint256 _value) private {
                                            setUint(keccak256("network.balance.total"), _value);
                                        }
                                        /// @notice The current RP network staking ETH balance
                                        function getStakingETHBalance() override public view returns (uint256) {
                                            return getUint(keccak256("network.balance.staking"));
                                        }
                                        /// @notice Sets the current RP network staking ETH balance
                                        function setStakingETHBalance(uint256 _value) private {
                                            setUint(keccak256("network.balance.staking"), _value);
                                        }
                                        /// @notice The current RP network total rETH supply
                                        function getTotalRETHSupply() override external view returns (uint256) {
                                            return getUint(keccak256("network.balance.reth.supply"));
                                        }
                                        /// @notice Sets the current RP network total rETH supply
                                        function setTotalRETHSupply(uint256 _value) private {
                                            setUint(keccak256("network.balance.reth.supply"), _value);
                                        }
                                        /// @notice Get the current RP network ETH utilization rate as a fraction of 1 ETH
                                        ///         Represents what % of the network's balance is actively earning rewards
                                        function getETHUtilizationRate() override external view returns (uint256) {
                                            uint256 totalEthBalance = getTotalETHBalance();
                                            uint256 stakingEthBalance = getStakingETHBalance();
                                            if (totalEthBalance == 0) { return calcBase; }
                                            return calcBase * stakingEthBalance / totalEthBalance;
                                        }
                                        /// @notice Submit network balances for a block.
                                        ///         Only accepts calls from trusted (oracle) nodes.
                                        function submitBalances(uint256 _block, uint256 _slotTimestamp, uint256 _totalEth, uint256 _stakingEth, uint256 _rethSupply) override external onlyLatestContract("rocketNetworkBalances", address(this)) onlyTrustedNode(msg.sender) {
                                            // Check settings
                                            RocketDAOProtocolSettingsNetworkInterface rocketDAOProtocolSettingsNetwork = RocketDAOProtocolSettingsNetworkInterface(getContractAddress("rocketDAOProtocolSettingsNetwork"));
                                            require(rocketDAOProtocolSettingsNetwork.getSubmitBalancesEnabled(), "Submitting balances is currently disabled");
                                            // Check block
                                            require(_block < block.number, "Balances can not be submitted for a future block");
                                            uint256 lastBalancesBlock = getBalancesBlock();
                                            require(_block >= lastBalancesBlock, "Network balances for a higher block are set");
                                            // Get submission keys
                                            bytes32 nodeSubmissionKey = keccak256(abi.encodePacked("network.balances.submitted.node", msg.sender, _block, _slotTimestamp, _totalEth, _stakingEth, _rethSupply));
                                            bytes32 submissionCountKey = keccak256(abi.encodePacked("network.balances.submitted.count", _block, _slotTimestamp, _totalEth, _stakingEth, _rethSupply));
                                            // Check & update node submission status
                                            require(!getBool(nodeSubmissionKey), "Duplicate submission from node");
                                            setBool(nodeSubmissionKey, true);
                                            setBool(keccak256(abi.encodePacked("network.balances.submitted.node", msg.sender, _block)), true);
                                            // Increment submission count
                                            uint256 submissionCount = getUint(submissionCountKey) + 1;
                                            setUint(submissionCountKey, submissionCount);
                                            // Emit balances submitted event
                                            emit BalancesSubmitted(msg.sender, _block, _slotTimestamp, _totalEth, _stakingEth, _rethSupply, block.timestamp);
                                            // If voting past consensus, return
                                            if (_block == lastBalancesBlock) {
                                                return;
                                            }
                                            // Check submission count & update network balances
                                            RocketDAONodeTrustedInterface rocketDAONodeTrusted = RocketDAONodeTrustedInterface(getContractAddress("rocketDAONodeTrusted"));
                                            if (calcBase * submissionCount / rocketDAONodeTrusted.getMemberCount() >= rocketDAOProtocolSettingsNetwork.getNodeConsensusThreshold()) {
                                                updateBalances(_block, _slotTimestamp, _totalEth, _stakingEth, _rethSupply);
                                            }
                                        }
                                        /// @notice Executes updateBalances if consensus threshold is reached
                                        function executeUpdateBalances(uint256 _block, uint256 _slotTimestamp, uint256 _totalEth, uint256 _stakingEth, uint256 _rethSupply) override external onlyLatestContract("rocketNetworkBalances", address(this)) {
                                            // Check settings
                                            RocketDAOProtocolSettingsNetworkInterface rocketDAOProtocolSettingsNetwork = RocketDAOProtocolSettingsNetworkInterface(getContractAddress("rocketDAOProtocolSettingsNetwork"));
                                            require(rocketDAOProtocolSettingsNetwork.getSubmitBalancesEnabled(), "Submitting balances is currently disabled");
                                            // Check block
                                            require(_block < block.number, "Balances can not be submitted for a future block");
                                            require(_block > getBalancesBlock(), "Network balances for an equal or higher block are set");
                                            // Check balances
                                            require(_stakingEth <= _totalEth, "Invalid network balances");
                                            // Get submission keys
                                            bytes32 submissionCountKey = keccak256(abi.encodePacked("network.balances.submitted.count", _block, _slotTimestamp, _totalEth, _stakingEth, _rethSupply));
                                            // Get submission count
                                            uint256 submissionCount = getUint(submissionCountKey);
                                            // Check submission count & update network balances
                                            RocketDAONodeTrustedInterface rocketDAONodeTrusted = RocketDAONodeTrustedInterface(getContractAddress("rocketDAONodeTrusted"));
                                            require(calcBase * submissionCount / rocketDAONodeTrusted.getMemberCount() >= rocketDAOProtocolSettingsNetwork.getNodeConsensusThreshold(), "Consensus has not been reached");
                                            updateBalances(_block, _slotTimestamp, _totalEth, _stakingEth, _rethSupply);
                                        }
                                        /// @dev Internal method to update network balances
                                        function updateBalances(uint256 _block, uint256 _slotTimestamp, uint256 _totalEth, uint256 _stakingEth, uint256 _rethSupply) private {
                                            // Update balances
                                            setBalancesBlock(_block);
                                            setTotalETHBalance(_totalEth);
                                            setStakingETHBalance(_stakingEth);
                                            setTotalRETHSupply(_rethSupply);
                                            // Emit balances updated event
                                            emit BalancesUpdated(_block, _slotTimestamp, _totalEth, _stakingEth, _rethSupply, block.timestamp);
                                        }
                                    }
                                    

                                    File 7 of 9: RocketMinipoolQueue
                                    // 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;
                                    /**
                                     * @title SignedSafeMath
                                     * @dev Signed math operations with safety checks that revert on error.
                                     */
                                    library SignedSafeMath {
                                        int256 constant private _INT256_MIN = -2**255;
                                        /**
                                         * @dev Returns the multiplication of two signed integers, reverting on
                                         * overflow.
                                         *
                                         * Counterpart to Solidity's `*` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - Multiplication cannot overflow.
                                         */
                                        function mul(int256 a, int256 b) internal pure returns (int256) {
                                            // 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 0;
                                            }
                                            require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");
                                            int256 c = a * b;
                                            require(c / a == b, "SignedSafeMath: multiplication overflow");
                                            return c;
                                        }
                                        /**
                                         * @dev Returns the integer division of two signed integers. Reverts 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(int256 a, int256 b) internal pure returns (int256) {
                                            require(b != 0, "SignedSafeMath: division by zero");
                                            require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");
                                            int256 c = a / b;
                                            return c;
                                        }
                                        /**
                                         * @dev Returns the subtraction of two signed integers, reverting on
                                         * overflow.
                                         *
                                         * Counterpart to Solidity's `-` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - Subtraction cannot overflow.
                                         */
                                        function sub(int256 a, int256 b) internal pure returns (int256) {
                                            int256 c = a - b;
                                            require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");
                                            return c;
                                        }
                                        /**
                                         * @dev Returns the addition of two signed integers, reverting on
                                         * overflow.
                                         *
                                         * Counterpart to Solidity's `+` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - Addition cannot overflow.
                                         */
                                        function add(int256 a, int256 b) internal pure returns (int256) {
                                            int256 c = a + b;
                                            require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");
                                            return c;
                                        }
                                    }
                                    // SPDX-License-Identifier: MIT
                                    pragma solidity >=0.6.0 <0.8.0;
                                    /**
                                     * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
                                     * checks.
                                     *
                                     * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
                                     * easily result in undesired exploitation or bugs, since developers usually
                                     * assume that overflows raise errors. `SafeCast` restores this intuition by
                                     * reverting the transaction when such 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.
                                     *
                                     * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
                                     * all math on `uint256` and `int256` and then downcasting.
                                     */
                                    library SafeCast {
                                        /**
                                         * @dev Returns the downcasted uint128 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint128).
                                         *
                                         * Counterpart to Solidity's `uint128` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 128 bits
                                         */
                                        function toUint128(uint256 value) internal pure returns (uint128) {
                                            require(value < 2**128, "SafeCast: value doesn\\'t fit in 128 bits");
                                            return uint128(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted uint64 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint64).
                                         *
                                         * Counterpart to Solidity's `uint64` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 64 bits
                                         */
                                        function toUint64(uint256 value) internal pure returns (uint64) {
                                            require(value < 2**64, "SafeCast: value doesn\\'t fit in 64 bits");
                                            return uint64(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted uint32 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint32).
                                         *
                                         * Counterpart to Solidity's `uint32` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 32 bits
                                         */
                                        function toUint32(uint256 value) internal pure returns (uint32) {
                                            require(value < 2**32, "SafeCast: value doesn\\'t fit in 32 bits");
                                            return uint32(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted uint16 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint16).
                                         *
                                         * Counterpart to Solidity's `uint16` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 16 bits
                                         */
                                        function toUint16(uint256 value) internal pure returns (uint16) {
                                            require(value < 2**16, "SafeCast: value doesn\\'t fit in 16 bits");
                                            return uint16(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted uint8 from uint256, reverting on
                                         * overflow (when the input is greater than largest uint8).
                                         *
                                         * Counterpart to Solidity's `uint8` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 8 bits.
                                         */
                                        function toUint8(uint256 value) internal pure returns (uint8) {
                                            require(value < 2**8, "SafeCast: value doesn\\'t fit in 8 bits");
                                            return uint8(value);
                                        }
                                        /**
                                         * @dev Converts a signed int256 into an unsigned uint256.
                                         *
                                         * Requirements:
                                         *
                                         * - input must be greater than or equal to 0.
                                         */
                                        function toUint256(int256 value) internal pure returns (uint256) {
                                            require(value >= 0, "SafeCast: value must be positive");
                                            return uint256(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int128 from int256, reverting on
                                         * overflow (when the input is less than smallest int128 or
                                         * greater than largest int128).
                                         *
                                         * Counterpart to Solidity's `int128` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 128 bits
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt128(int256 value) internal pure returns (int128) {
                                            require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\\'t fit in 128 bits");
                                            return int128(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int64 from int256, reverting on
                                         * overflow (when the input is less than smallest int64 or
                                         * greater than largest int64).
                                         *
                                         * Counterpart to Solidity's `int64` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 64 bits
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt64(int256 value) internal pure returns (int64) {
                                            require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\\'t fit in 64 bits");
                                            return int64(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int32 from int256, reverting on
                                         * overflow (when the input is less than smallest int32 or
                                         * greater than largest int32).
                                         *
                                         * Counterpart to Solidity's `int32` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 32 bits
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt32(int256 value) internal pure returns (int32) {
                                            require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\\'t fit in 32 bits");
                                            return int32(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int16 from int256, reverting on
                                         * overflow (when the input is less than smallest int16 or
                                         * greater than largest int16).
                                         *
                                         * Counterpart to Solidity's `int16` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 16 bits
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt16(int256 value) internal pure returns (int16) {
                                            require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\\'t fit in 16 bits");
                                            return int16(value);
                                        }
                                        /**
                                         * @dev Returns the downcasted int8 from int256, reverting on
                                         * overflow (when the input is less than smallest int8 or
                                         * greater than largest int8).
                                         *
                                         * Counterpart to Solidity's `int8` operator.
                                         *
                                         * Requirements:
                                         *
                                         * - input must fit into 8 bits.
                                         *
                                         * _Available since v3.1._
                                         */
                                        function toInt8(int256 value) internal pure returns (int8) {
                                            require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\\'t fit in 8 bits");
                                            return int8(value);
                                        }
                                        /**
                                         * @dev Converts an unsigned uint256 into a signed int256.
                                         *
                                         * Requirements:
                                         *
                                         * - input must be less than or equal to maxInt256.
                                         */
                                        function toInt256(uint256 value) internal pure returns (int256) {
                                            require(value < 2**255, "SafeCast: value doesn't fit in an int256");
                                            return int256(value);
                                        }
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
                                      * +---------------------------------------------------+
                                      *
                                      *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
                                      *  decentralised, trustless and compatible with staking in Ethereum 2.0.
                                      *
                                      *  For more information about Rocket Pool, visit https://rocketpool.net
                                      *
                                      *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
                                      *
                                      */
                                    pragma solidity >0.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
                                    import "../interface/RocketStorageInterface.sol";
                                    /// @title Base settings / modifiers for each contract in Rocket Pool
                                    /// @author David Rugendyke
                                    abstract contract RocketBase {
                                        // Calculate using this as the base
                                        uint256 constant calcBase = 1 ether;
                                        // Version of the contract
                                        uint8 public version;
                                        // The main storage contract where primary persistant storage is maintained
                                        RocketStorageInterface rocketStorage = RocketStorageInterface(0);
                                        /*** Modifiers **********************************************************/
                                        /**
                                        * @dev Throws if called by any sender that doesn't match a Rocket Pool network contract
                                        */
                                        modifier onlyLatestNetworkContract() {
                                            require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract");
                                            _;
                                        }
                                        /**
                                        * @dev Throws if called by any sender that doesn't match one of the supplied contract or is the latest version of that contract
                                        */
                                        modifier onlyLatestContract(string memory _contractName, address _contractAddress) {
                                            require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract");
                                            _;
                                        }
                                        /**
                                        * @dev Throws if called by any sender that isn't a registered node
                                        */
                                        modifier onlyRegisteredNode(address _nodeAddress) {
                                            require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node");
                                            _;
                                        }
                                        /**
                                        * @dev Throws if called by any sender that isn't a trusted node DAO member
                                        */
                                        modifier onlyTrustedNode(address _nodeAddress) {
                                            require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node");
                                            _;
                                        }
                                        /**
                                        * @dev Throws if called by any sender that isn't a registered minipool
                                        */
                                        modifier onlyRegisteredMinipool(address _minipoolAddress) {
                                            require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool");
                                            _;
                                        }
                                        
                                        /**
                                        * @dev Throws if called by any account other than a guardian account (temporary account allowed access to settings before DAO is fully enabled)
                                        */
                                        modifier onlyGuardian() {
                                            require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian");
                                            _;
                                        }
                                        /*** Methods **********************************************************/
                                        /// @dev Set the main Rocket Storage address
                                        constructor(RocketStorageInterface _rocketStorageAddress) {
                                            // Update the contract address
                                            rocketStorage = RocketStorageInterface(_rocketStorageAddress);
                                        }
                                        /// @dev Get the address of a network contract by name
                                        function getContractAddress(string memory _contractName) internal view returns (address) {
                                            // Get the current contract address
                                            address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
                                            // Check it
                                            require(contractAddress != address(0x0), "Contract not found");
                                            // Return
                                            return contractAddress;
                                        }
                                        /// @dev Get the address of a network contract by name (returns address(0x0) instead of reverting if contract does not exist)
                                        function getContractAddressUnsafe(string memory _contractName) internal view returns (address) {
                                            // Get the current contract address
                                            address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
                                            // Return
                                            return contractAddress;
                                        }
                                        /// @dev Get the name of a network contract by address
                                        function getContractName(address _contractAddress) internal view returns (string memory) {
                                            // Get the contract name
                                            string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress)));
                                            // Check it
                                            require(bytes(contractName).length > 0, "Contract not found");
                                            // Return
                                            return contractName;
                                        }
                                        /// @dev Get revert error message from a .call method
                                        function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
                                            // If the _res length is less than 68, then the transaction failed silently (without a revert message)
                                            if (_returnData.length < 68) return "Transaction reverted silently";
                                            assembly {
                                                // Slice the sighash.
                                                _returnData := add(_returnData, 0x04)
                                            }
                                            return abi.decode(_returnData, (string)); // All that remains is the revert string
                                        }
                                        /*** Rocket Storage Methods ****************************************/
                                        // Note: Unused helpers have been removed to keep contract sizes down
                                        /// @dev Storage get methods
                                        function getAddress(bytes32 _key) internal view returns (address) { return rocketStorage.getAddress(_key); }
                                        function getUint(bytes32 _key) internal view returns (uint) { return rocketStorage.getUint(_key); }
                                        function getString(bytes32 _key) internal view returns (string memory) { return rocketStorage.getString(_key); }
                                        function getBytes(bytes32 _key) internal view returns (bytes memory) { return rocketStorage.getBytes(_key); }
                                        function getBool(bytes32 _key) internal view returns (bool) { return rocketStorage.getBool(_key); }
                                        function getInt(bytes32 _key) internal view returns (int) { return rocketStorage.getInt(_key); }
                                        function getBytes32(bytes32 _key) internal view returns (bytes32) { return rocketStorage.getBytes32(_key); }
                                        /// @dev Storage set methods
                                        function setAddress(bytes32 _key, address _value) internal { rocketStorage.setAddress(_key, _value); }
                                        function setUint(bytes32 _key, uint _value) internal { rocketStorage.setUint(_key, _value); }
                                        function setString(bytes32 _key, string memory _value) internal { rocketStorage.setString(_key, _value); }
                                        function setBytes(bytes32 _key, bytes memory _value) internal { rocketStorage.setBytes(_key, _value); }
                                        function setBool(bytes32 _key, bool _value) internal { rocketStorage.setBool(_key, _value); }
                                        function setInt(bytes32 _key, int _value) internal { rocketStorage.setInt(_key, _value); }
                                        function setBytes32(bytes32 _key, bytes32 _value) internal { rocketStorage.setBytes32(_key, _value); }
                                        /// @dev Storage delete methods
                                        function deleteAddress(bytes32 _key) internal { rocketStorage.deleteAddress(_key); }
                                        function deleteUint(bytes32 _key) internal { rocketStorage.deleteUint(_key); }
                                        function deleteString(bytes32 _key) internal { rocketStorage.deleteString(_key); }
                                        function deleteBytes(bytes32 _key) internal { rocketStorage.deleteBytes(_key); }
                                        function deleteBool(bytes32 _key) internal { rocketStorage.deleteBool(_key); }
                                        function deleteInt(bytes32 _key) internal { rocketStorage.deleteInt(_key); }
                                        function deleteBytes32(bytes32 _key) internal { rocketStorage.deleteBytes32(_key); }
                                        /// @dev Storage arithmetic methods
                                        function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); }
                                        function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); }
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
                                      * +---------------------------------------------------+
                                      *
                                      *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
                                      *  decentralised, trustless and compatible with staking in Ethereum 2.0.
                                      *
                                      *  For more information about Rocket Pool, visit https://rocketpool.net
                                      *
                                      *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
                                      *
                                      */
                                    pragma solidity 0.7.6;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    // 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.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    import "../../types/MinipoolDeposit.sol";
                                    import "../../types/MinipoolStatus.sol";
                                    import "../RocketStorageInterface.sol";
                                    interface RocketMinipoolInterface {
                                        function version() external view returns (uint8);
                                        function initialise(address _nodeAddress) external;
                                        function getStatus() external view returns (MinipoolStatus);
                                        function getFinalised() external view returns (bool);
                                        function getStatusBlock() external view returns (uint256);
                                        function getStatusTime() external view returns (uint256);
                                        function getScrubVoted(address _member) external view returns (bool);
                                        function getDepositType() external view returns (MinipoolDeposit);
                                        function getNodeAddress() external view returns (address);
                                        function getNodeFee() external view returns (uint256);
                                        function getNodeDepositBalance() external view returns (uint256);
                                        function getNodeRefundBalance() external view returns (uint256);
                                        function getNodeDepositAssigned() external view returns (bool);
                                        function getPreLaunchValue() external view returns (uint256);
                                        function getNodeTopUpValue() external view returns (uint256);
                                        function getVacant() external view returns (bool);
                                        function getPreMigrationBalance() external view returns (uint256);
                                        function getUserDistributed() external view returns (bool);
                                        function getUserDepositBalance() external view returns (uint256);
                                        function getUserDepositAssigned() external view returns (bool);
                                        function getUserDepositAssignedTime() external view returns (uint256);
                                        function getTotalScrubVotes() external view returns (uint256);
                                        function calculateNodeShare(uint256 _balance) external view returns (uint256);
                                        function calculateUserShare(uint256 _balance) external view returns (uint256);
                                        function preDeposit(uint256 _bondingValue, bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot) external payable;
                                        function deposit() external payable;
                                        function userDeposit() external payable;
                                        function distributeBalance(bool _rewardsOnly) external;
                                        function beginUserDistribute() external;
                                        function userDistributeAllowed() external view returns (bool);
                                        function refund() external;
                                        function slash() external;
                                        function finalise() external;
                                        function canStake() external view returns (bool);
                                        function canPromote() external view returns (bool);
                                        function stake(bytes calldata _validatorSignature, bytes32 _depositDataRoot) external;
                                        function prepareVacancy(uint256 _bondAmount, uint256 _currentBalance) external;
                                        function promote() external;
                                        function dissolve() external;
                                        function close() external;
                                        function voteScrub() external;
                                        function reduceBondAmount() external;
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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
                                    import "../../types/MinipoolDeposit.sol";
                                    interface RocketMinipoolQueueInterface {
                                        function getTotalLength() external view returns (uint256);
                                        function getContainsLegacy() external view returns (bool);
                                        function getLengthLegacy(MinipoolDeposit _depositType) external view returns (uint256);
                                        function getLength() external view returns (uint256);
                                        function getTotalCapacity() external view returns (uint256);
                                        function getEffectiveCapacity() external view returns (uint256);
                                        function getNextCapacityLegacy() external view returns (uint256);
                                        function getNextDepositLegacy() external view returns (MinipoolDeposit, uint256);
                                        function enqueueMinipool(address _minipool) external;
                                        function dequeueMinipoolByDepositLegacy(MinipoolDeposit _depositType) external returns (address minipoolAddress);
                                        function dequeueMinipools(uint256 _maxToDequeue) external returns (address[] memory minipoolAddress);
                                        function removeMinipool(MinipoolDeposit _depositType) external;
                                        function getMinipoolAt(uint256 _index) external view returns(address);
                                        function getMinipoolPosition(address _minipool) external view returns (int256);
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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
                                    import "../../../../types/MinipoolDeposit.sol";
                                    interface RocketDAOProtocolSettingsMinipoolInterface {
                                        function getLaunchBalance() external view returns (uint256);
                                        function getPreLaunchValue() external pure returns (uint256);
                                        function getDepositUserAmount(MinipoolDeposit _depositType) external view returns (uint256);
                                        function getFullDepositUserAmount() external view returns (uint256);
                                        function getHalfDepositUserAmount() external view returns (uint256);
                                        function getVariableDepositAmount() external view returns (uint256);
                                        function getSubmitWithdrawableEnabled() external view returns (bool);
                                        function getBondReductionEnabled() external view returns (bool);
                                        function getLaunchTimeout() external view returns (uint256);
                                        function getMaximumCount() external view returns (uint256);
                                        function isWithinUserDistributeWindow(uint256 _time) external view returns (bool);
                                        function hasUserDistributeWindowPassed(uint256 _time) external view returns (bool);
                                        function getUserDistributeWindowStart() external view returns (uint256);
                                        function getUserDistributeWindowLength() external view returns (uint256);
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  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 AddressQueueStorageInterface {
                                        function getLength(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 enqueueItem(bytes32 _key, address _value) external;
                                        function dequeueItem(bytes32 _key) external returns (address);
                                        function removeItem(bytes32 _key, address _value) external;
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |  DECENTRALISED STAKING PROTOCOL FOR ETHEREUM 2.0  |
                                      * +---------------------------------------------------+
                                      *
                                      *  Rocket Pool is a first-of-its-kind ETH2 Proof of Stake protocol, designed to be community owned,
                                      *  decentralised, trustless and compatible with staking in Ethereum 2.0.
                                      *
                                      *  For more information about Rocket Pool, visit https://rocketpool.net
                                      *
                                      *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
                                      *
                                      */
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    pragma solidity 0.7.6;
                                    import "@openzeppelin/contracts/math/SafeMath.sol";
                                    import "@openzeppelin/contracts/math/SignedSafeMath.sol";
                                    import "@openzeppelin/contracts/utils/SafeCast.sol";
                                    import "../RocketBase.sol";
                                    import "../../interface/minipool/RocketMinipoolInterface.sol";
                                    import "../../interface/minipool/RocketMinipoolQueueInterface.sol";
                                    import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsMinipoolInterface.sol";
                                    import "../../interface/util/AddressQueueStorageInterface.sol";
                                    import "../../types/MinipoolDeposit.sol";
                                    /// @notice Minipool queueing for deposit assignment
                                    contract RocketMinipoolQueue is RocketBase, RocketMinipoolQueueInterface {
                                        // Libs
                                        using SafeMath for uint;
                                        using SignedSafeMath for int;
                                        // Constants
                                        bytes32 private constant queueKeyFull = keccak256("minipools.available.full");
                                        bytes32 private constant queueKeyHalf = keccak256("minipools.available.half");
                                        bytes32 private constant queueKeyVariable = keccak256("minipools.available.variable");
                                        // Events
                                        event MinipoolEnqueued(address indexed minipool, bytes32 indexed queueId, uint256 time);
                                        event MinipoolDequeued(address indexed minipool, bytes32 indexed queueId, uint256 time);
                                        event MinipoolRemoved(address indexed minipool, bytes32 indexed queueId, uint256 time);
                                        constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
                                            version = 2;
                                        }
                                        /// @notice Get the total combined length of the queues
                                        function getTotalLength() override external view returns (uint256) {
                                            return (
                                                getLengthLegacy(queueKeyFull)
                                            ).add(
                                                getLengthLegacy(queueKeyHalf)
                                            ).add(
                                                getLength()
                                            );
                                        }
                                        /// @notice Returns true if there are any legacy minipools in the queue
                                        function getContainsLegacy() override external view returns (bool) {
                                            return getLengthLegacy(queueKeyFull).add(getLengthLegacy(queueKeyHalf)) > 0;
                                        }
                                        /// @notice Get the length of a given queue. Returns 0 for invalid queues
                                        /// @param _depositType Which queue to query the length of
                                        function getLengthLegacy(MinipoolDeposit _depositType) override external view returns (uint256) {
                                            if (_depositType == MinipoolDeposit.Full) { return getLengthLegacy(queueKeyFull); }
                                            if (_depositType == MinipoolDeposit.Half) { return getLengthLegacy(queueKeyHalf); }
                                            return 0;
                                        }
                                        /// @dev Returns a queue length by internal key representation
                                        /// @param _key The internal key representation of the queue to query the length of
                                        function getLengthLegacy(bytes32 _key) private view returns (uint256) {
                                            AddressQueueStorageInterface addressQueueStorage = AddressQueueStorageInterface(getContractAddress("addressQueueStorage"));
                                            return addressQueueStorage.getLength(_key);
                                        }
                                        /// @notice Gets the length of the variable (global) queue
                                        function getLength() override public view returns (uint256) {
                                            AddressQueueStorageInterface addressQueueStorage = AddressQueueStorageInterface(getContractAddress("addressQueueStorage"));
                                            return addressQueueStorage.getLength(queueKeyVariable);
                                        }
                                        /// @notice Get the total combined capacity of the queues
                                        function getTotalCapacity() override external view returns (uint256) {
                                            RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
                                            return (
                                                getLengthLegacy(queueKeyFull).mul(rocketDAOProtocolSettingsMinipool.getFullDepositUserAmount())
                                            ).add(
                                                getLengthLegacy(queueKeyHalf).mul(rocketDAOProtocolSettingsMinipool.getHalfDepositUserAmount())
                                            ).add(
                                                getVariableCapacity()
                                            );
                                        }
                                        /// @notice Get the total effective capacity of the queues (used in node demand calculation)
                                        function getEffectiveCapacity() override external view returns (uint256) {
                                            RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
                                            return (
                                                getLengthLegacy(queueKeyFull).mul(rocketDAOProtocolSettingsMinipool.getFullDepositUserAmount())
                                            ).add(
                                                getLengthLegacy(queueKeyHalf).mul(rocketDAOProtocolSettingsMinipool.getHalfDepositUserAmount())
                                            ).add(
                                                getVariableCapacity()
                                            );
                                        }
                                        /// @dev Get the ETH capacity of the variable queue
                                        function getVariableCapacity() internal view returns (uint256) {
                                            RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
                                            return getLength().mul(rocketDAOProtocolSettingsMinipool.getVariableDepositAmount());
                                        }
                                        /// @notice Get the capacity of the next available minipool. Returns 0 if no minipools are available
                                        function getNextCapacityLegacy() override external view returns (uint256) {
                                            RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
                                            if (getLengthLegacy(queueKeyHalf) > 0) { return rocketDAOProtocolSettingsMinipool.getHalfDepositUserAmount(); }
                                            if (getLengthLegacy(queueKeyFull) > 0) { return rocketDAOProtocolSettingsMinipool.getFullDepositUserAmount(); }
                                            return 0;
                                        }
                                        /// @notice Get the deposit type of the next available minipool and the number of deposits in that queue.
                                        ///         Returns None if no minipools are available
                                        function getNextDepositLegacy() override external view returns (MinipoolDeposit, uint256) {
                                            uint256 length = getLengthLegacy(queueKeyHalf);
                                            if (length > 0) { return (MinipoolDeposit.Half, length); }
                                            length = getLengthLegacy(queueKeyFull);
                                            if (length > 0) { return (MinipoolDeposit.Full, length); }
                                            return (MinipoolDeposit.None, 0);
                                        }
                                        /// @dev Add a minipool to the end of the appropriate queue. Only accepts calls from the RocketMinipoolManager contract
                                        /// @param _minipool Address of the minipool to add to the queue
                                        function enqueueMinipool(address _minipool) override external onlyLatestContract("rocketMinipoolQueue", address(this)) onlyLatestContract("rocketNodeDeposit", msg.sender) {
                                            // Enqueue
                                            AddressQueueStorageInterface addressQueueStorage = AddressQueueStorageInterface(getContractAddress("addressQueueStorage"));
                                            addressQueueStorage.enqueueItem(queueKeyVariable, _minipool);
                                            // Emit enqueued event
                                            emit MinipoolEnqueued(_minipool, queueKeyVariable, block.timestamp);
                                        }
                                        /// @dev Dequeues a minipool from a legacy queue
                                        /// @param _depositType The queue to dequeue a minipool from
                                        function dequeueMinipoolByDepositLegacy(MinipoolDeposit _depositType) override external onlyLatestContract("rocketMinipoolQueue", address(this)) onlyLatestContract("rocketDepositPool", msg.sender) returns (address minipoolAddress) {
                                            if (_depositType == MinipoolDeposit.Half) { return dequeueMinipool(queueKeyHalf); }
                                            if (_depositType == MinipoolDeposit.Full) { return dequeueMinipool(queueKeyFull); }
                                            require(false, "No minipools are available");
                                        }
                                        /// @dev Dequeues multiple minipools from the variable queue and returns them all
                                        /// @param _maxToDequeue The maximum number of items to dequeue
                                        function dequeueMinipools(uint256 _maxToDequeue) override external onlyLatestContract("rocketMinipoolQueue", address(this)) onlyLatestContract("rocketDepositPool", msg.sender) returns (address[] memory minipoolAddress) {
                                            uint256 queueLength = getLength();
                                            uint256 count = _maxToDequeue;
                                            if (count > queueLength) {
                                                count = queueLength;
                                            }
                                            address[] memory minipoolAddresses = new address[](count);
                                            for (uint256 i = 0; i < count; i++) {
                                                RocketMinipoolInterface minipool = RocketMinipoolInterface(dequeueMinipool(queueKeyVariable));
                                                minipoolAddresses[i] = address(minipool);
                                            }
                                            return minipoolAddresses;
                                        }
                                        /// @dev Dequeues a minipool from a queue given an internal key
                                        /// @param _key The internal key representation of the queue from which to dequeue a minipool from
                                        function dequeueMinipool(bytes32 _key) private returns (address) {
                                            // Dequeue
                                            AddressQueueStorageInterface addressQueueStorage = AddressQueueStorageInterface(getContractAddress("addressQueueStorage"));
                                            address minipool = addressQueueStorage.dequeueItem(_key);
                                            // Emit dequeued event
                                            emit MinipoolDequeued(minipool, _key, block.timestamp);
                                            // Return
                                            return minipool;
                                        }
                                        /// @dev Remove a minipool from a queue. Only accepts calls from registered minipools
                                        function removeMinipool(MinipoolDeposit _depositType) override external onlyLatestContract("rocketMinipoolQueue", address(this)) onlyRegisteredMinipool(msg.sender) {
                                            // Remove minipool from queue
                                            if (_depositType == MinipoolDeposit.Half) { return removeMinipool(queueKeyHalf, msg.sender); }
                                            if (_depositType == MinipoolDeposit.Full) { return removeMinipool(queueKeyFull, msg.sender); }
                                            if (_depositType == MinipoolDeposit.Variable) { return removeMinipool(queueKeyVariable, msg.sender); }
                                            require(false, "Invalid minipool deposit type");
                                        }
                                        /// @dev Removes a minipool from a queue given an internal key
                                        /// @param _key The internal key representation of the queue from which to remove a minipool from
                                        /// @param _minipool The address of a minipool to remove from the specified queue
                                        function removeMinipool(bytes32 _key, address _minipool) private {
                                            // Remove
                                            AddressQueueStorageInterface addressQueueStorage = AddressQueueStorageInterface(getContractAddress("addressQueueStorage"));
                                            addressQueueStorage.removeItem(_key, _minipool);
                                            // Emit removed event
                                            emit MinipoolRemoved(_minipool, _key, block.timestamp);
                                        }
                                        /// @notice Returns the minipool address of the minipool in the global queue at a given index
                                        /// @param _index The index into the queue to retrieve
                                        function getMinipoolAt(uint256 _index) override external view returns(address) {
                                            AddressQueueStorageInterface addressQueueStorage = AddressQueueStorageInterface(getContractAddress("addressQueueStorage"));
                                            // Check if index is in the half queue
                                            uint256 halfLength = addressQueueStorage.getLength(queueKeyHalf);
                                            if (_index < halfLength) {
                                                return addressQueueStorage.getItem(queueKeyHalf, _index);
                                            }
                                            _index = _index.sub(halfLength);
                                            // Check if index is in the full queue
                                            uint256 fullLength = addressQueueStorage.getLength(queueKeyFull);
                                            if (_index < fullLength) {
                                                return addressQueueStorage.getItem(queueKeyFull, _index);
                                            }
                                            _index = _index.sub(fullLength);
                                            // Check if index is in the full queue
                                            uint256 variableLength = addressQueueStorage.getLength(queueKeyVariable);
                                            if (_index < variableLength) {
                                                return addressQueueStorage.getItem(queueKeyVariable, _index);
                                            }
                                            // Index is out of bounds
                                            return address(0);
                                        }
                                        /// @notice Returns the position a given minipool is in the queue
                                        /// @param _minipool The minipool to query the position of
                                        function getMinipoolPosition(address _minipool) override external view returns (int256) {
                                            AddressQueueStorageInterface addressQueueStorage = AddressQueueStorageInterface(getContractAddress("addressQueueStorage"));
                                            int256 position;
                                            // Check in half queue
                                            position = addressQueueStorage.getIndexOf(queueKeyHalf, _minipool);
                                            if (position != -1) {
                                                return position;
                                            }
                                            int256 offset = SafeCast.toInt256(addressQueueStorage.getLength(queueKeyHalf));
                                            // Check in full queue
                                            position = addressQueueStorage.getIndexOf(queueKeyFull, _minipool);
                                            if (position != -1) {
                                                return offset.add(position);
                                            }
                                            offset = offset.add(SafeCast.toInt256(addressQueueStorage.getLength(queueKeyFull)));
                                            // Check in variable queue
                                            position = addressQueueStorage.getIndexOf(queueKeyVariable, _minipool);
                                            if (position != -1) {
                                                return offset.add(position);
                                            }
                                            // Isn't in the queue
                                            return -1;
                                        }
                                    }
                                    

                                    File 8 of 9: AddressQueueStorage
                                    // 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/util/AddressQueueStorageInterface.sol";
                                    import "@openzeppelin/contracts/math/SafeMath.sol";
                                    // Address queue storage helper for RocketStorage data (ring buffer implementation)
                                    contract AddressQueueStorage is RocketBase, AddressQueueStorageInterface {
                                        // Libs
                                        using SafeMath for uint256;
                                        // Settings
                                        uint256 constant public capacity = 2 ** 255; // max uint256 / 2
                                        // Construct
                                        constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
                                            version = 1;
                                        }
                                        // The number of items in a queue
                                        function getLength(bytes32 _key) override public view returns (uint) {
                                            uint start = getUint(keccak256(abi.encodePacked(_key, ".start")));
                                            uint end = getUint(keccak256(abi.encodePacked(_key, ".end")));
                                            if (end < start) { end = end.add(capacity); }
                                            return end.sub(start);
                                        }
                                        // The item in a queue by index
                                        function getItem(bytes32 _key, uint _index) override external view returns (address) {
                                            uint index = getUint(keccak256(abi.encodePacked(_key, ".start"))).add(_index);
                                            if (index >= capacity) { index = index.sub(capacity); }
                                            return getAddress(keccak256(abi.encodePacked(_key, ".item", index)));
                                        }
                                        // The index of an item in a queue
                                        // Returns -1 if the value is not found
                                        function getIndexOf(bytes32 _key, address _value) override external view returns (int) {
                                            int index = int(getUint(keccak256(abi.encodePacked(_key, ".index", _value)))) - 1;
                                            if (index != -1) {
                                                index -= int(getUint(keccak256(abi.encodePacked(_key, ".start"))));
                                                if (index < 0) { index += int(capacity); }
                                            }
                                            return index;
                                        }
                                        // Add an item to the end of a queue
                                        // Requires that the queue is not at capacity
                                        // Requires that the item does not exist in the queue
                                        function enqueueItem(bytes32 _key, address _value) override external onlyLatestContract("addressQueueStorage", address(this)) onlyLatestNetworkContract {
                                            require(getLength(_key) < capacity.sub(1), "Queue is at capacity");
                                            require(getUint(keccak256(abi.encodePacked(_key, ".index", _value))) == 0, "Item already exists in queue");
                                            uint index = getUint(keccak256(abi.encodePacked(_key, ".end")));
                                            setAddress(keccak256(abi.encodePacked(_key, ".item", index)), _value);
                                            setUint(keccak256(abi.encodePacked(_key, ".index", _value)), index.add(1));
                                            index = index.add(1);
                                            if (index >= capacity) { index = index.sub(capacity); }
                                            setUint(keccak256(abi.encodePacked(_key, ".end")), index);
                                        }
                                        // Remove an item from the start of a queue and return it
                                        // Requires that the queue is not empty
                                        function dequeueItem(bytes32 _key) override external onlyLatestContract("addressQueueStorage", address(this)) onlyLatestNetworkContract returns (address) {
                                            require(getLength(_key) > 0, "Queue is empty");
                                            uint start = getUint(keccak256(abi.encodePacked(_key, ".start")));
                                            address item = getAddress(keccak256(abi.encodePacked(_key, ".item", start)));
                                            start = start.add(1);
                                            if (start >= capacity) { start = start.sub(capacity); }
                                            setUint(keccak256(abi.encodePacked(_key, ".index", item)), 0);
                                            setUint(keccak256(abi.encodePacked(_key, ".start")), start);
                                            return item;
                                        }
                                        // Remove an item from a queue
                                        // Swaps the item with the last item in the queue and truncates it; computationally cheap
                                        // Requires that the item exists in the queue
                                        function removeItem(bytes32 _key, address _value) override external onlyLatestContract("addressQueueStorage", address(this)) onlyLatestNetworkContract {
                                            uint index = getUint(keccak256(abi.encodePacked(_key, ".index", _value)));
                                            require(index-- > 0, "Item does not exist in queue");
                                            uint lastIndex = getUint(keccak256(abi.encodePacked(_key, ".end")));
                                            if (lastIndex == 0) lastIndex = capacity;
                                            lastIndex = lastIndex.sub(1);
                                            if (index != lastIndex) {
                                                address lastItem = getAddress(keccak256(abi.encodePacked(_key, ".item", lastIndex)));
                                                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, ".end")), lastIndex);
                                        }
                                    }
                                    /**
                                      *       .
                                      *      / \\
                                      *     |.'.|
                                      *     |'.'|
                                      *   ,'|   |`.
                                      *  |,-'-|-'-.|
                                      *   __|_| |         _        _      _____           _
                                      *  | ___ \\|        | |      | |    | ___ \\         | |
                                      *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                      *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                      *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                      *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                      * +---------------------------------------------------+
                                      * |    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 AddressQueueStorageInterface {
                                        function getLength(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 enqueueItem(bytes32 _key, address _value) external;
                                        function dequeueItem(bytes32 _key) external returns (address);
                                        function removeItem(bytes32 _key, address _value) external;
                                    }
                                    

                                    File 9 of 9: RocketDAOProtocolSettingsMinipool
                                    /**
                                       *       .
                                       *      / \\
                                       *     |.'.|
                                       *     |'.'|
                                       *   ,'|   |'.
                                       *  |,-'-|-'-.|
                                       *   __|_| |         _        _      _____           _
                                       *  | ___ \\|        | |      | |    | ___ \\         | |
                                       *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                       *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                       *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                       *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                       * +---------------------------------------------------+
                                       * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    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    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // 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(address(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, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // 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, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    pragma solidity >0.5.0 <0.9.0;
                                    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, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // 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    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    import "../../../../types/MinipoolDeposit.sol";
                                    interface RocketDAOProtocolSettingsMinipoolInterface {
                                        function getLaunchBalance() external view returns (uint256);
                                        function getPreLaunchValue() external pure returns (uint256);
                                        function getDepositUserAmount(MinipoolDeposit _depositType) external view returns (uint256);
                                        function getFullDepositUserAmount() external view returns (uint256);
                                        function getHalfDepositUserAmount() external view returns (uint256);
                                        function getVariableDepositAmount() external view returns (uint256);
                                        function getSubmitWithdrawableEnabled() external view returns (bool);
                                        function getBondReductionEnabled() external view returns (bool);
                                        function getLaunchTimeout() external view returns (uint256);
                                        function getMaximumCount() external view returns (uint256);
                                        function isWithinUserDistributeWindow(uint256 _time) external view returns (bool);
                                        function hasUserDistributeWindowPassed(uint256 _time) external view returns (bool);
                                        function getUserDistributeWindowStart() external view returns (uint256);
                                        function getUserDistributeWindowLength() external view returns (uint256);
                                    }
                                    /**
                                       *       .
                                       *      / \\
                                       *     |.'.|
                                       *     |'.'|
                                       *   ,'|   |'.
                                       *  |,-'-|-'-.|
                                       *   __|_| |         _        _      _____           _
                                       *  | ___ \\|        | |      | |    | ___ \\         | |
                                       *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                       *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                       *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                       *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                       * +---------------------------------------------------+
                                       * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    pragma solidity >0.5.0 <0.9.0;
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    interface RocketDAONodeTrustedSettingsMinipoolInterface {
                                        function getScrubPeriod() external view returns(uint256);
                                        function getPromotionScrubPeriod() external view returns(uint256);
                                        function getScrubQuorum() external view returns(uint256);
                                        function getCancelBondReductionQuorum() external view returns(uint256);
                                        function getScrubPenaltyEnabled() external view returns(bool);
                                        function isWithinBondReductionWindow(uint256 _time) external view returns (bool);
                                        function getBondReductionWindowStart() external view returns (uint256);
                                        function getBondReductionWindowLength() external view returns (uint256);
                                    }
                                    /**
                                       *       .
                                       *      / \\
                                       *     |.'.|
                                       *     |'.'|
                                       *   ,'|   |'.
                                       *  |,-'-|-'-.|
                                       *   __|_| |         _        _      _____           _
                                       *  | ___ \\|        | |      | |    | ___ \\         | |
                                       *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
                                       *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
                                       *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
                                       *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
                                       * +---------------------------------------------------+
                                       * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
                                       * +---------------------------------------------------+
                                       *
                                       *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
                                       *  be community-owned, decentralised, permissionless, & trustless.
                                       *
                                       *  For more information about Rocket Pool, visit https://rocketpool.net
                                       *
                                       *  Authored by the Rocket Pool Core Team
                                       *  Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
                                       *  A special thanks to the Rocket Pool community for all their contributions.
                                       *
                                       */
                                    // SPDX-License-Identifier: GPL-3.0-only
                                    pragma solidity 0.8.18;
                                    import "./RocketDAOProtocolSettings.sol";
                                    import "../../../../interface/dao/protocol/settings/RocketDAOProtocolSettingsMinipoolInterface.sol";
                                    import "../../../../interface/dao/node/settings/RocketDAONodeTrustedSettingsMinipoolInterface.sol";
                                    import "../../../../types/MinipoolDeposit.sol";
                                    /// @notice Network minipool settings
                                    contract RocketDAOProtocolSettingsMinipool is RocketDAOProtocolSettings, RocketDAOProtocolSettingsMinipoolInterface {
                                        uint256 constant internal minipoolUserDistributeWindowStart = 90 days;
                                        constructor(RocketStorageInterface _rocketStorageAddress) RocketDAOProtocolSettings(_rocketStorageAddress, "minipool") {
                                            version = 3;
                                            // Initialize settings on deployment
                                            if(!getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")))) {
                                                // Apply settings
                                                setSettingBool("minipool.submit.withdrawable.enabled", false);
                                                setSettingBool("minipool.bond.reduction.enabled", false);
                                                setSettingUint("minipool.launch.timeout", 72 hours);
                                                setSettingUint("minipool.maximum.count", 14);
                                                setSettingUint("minipool.user.distribute.window.length", 2 days);
                                                // Settings initialised
                                                setBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")), true);
                                            }
                                        }
                                        /// @notice Update a setting, overrides inherited setting method with extra checks for this contract
                                        /// @param _settingPath The path of the setting within this contract's namespace
                                        /// @param _value The value to set it to
                                        function setSettingUint(string memory _settingPath, uint256 _value) override public onlyDAOProtocolProposal {
                                            // Some safety guards for certain settings
                                            if(getBool(keccak256(abi.encodePacked(settingNameSpace, "deployed")))) {
                                                bytes32 settingKey = keccak256(abi.encodePacked(_settingPath));
                                                if(settingKey == keccak256(abi.encodePacked("minipool.launch.timeout"))) {
                                                    RocketDAONodeTrustedSettingsMinipoolInterface rocketDAONodeTrustedSettingsMinipool = RocketDAONodeTrustedSettingsMinipoolInterface(getContractAddress("rocketDAONodeTrustedSettingsMinipool"));
                                                    require(_value >= (rocketDAONodeTrustedSettingsMinipool.getScrubPeriod() + 1 hours), "Launch timeout must be greater than scrub period");
                                                    // >= 12 hours (RPIP-33)
                                                    require(_value >= 12 hours, "Launch timeout must be greater than 12 hours");
                                                } 
                                            }
                                            // Update setting now
                                            setUint(keccak256(abi.encodePacked(settingNameSpace, _settingPath)), _value);
                                        }
                                        /// @notice Returns the balance required to launch minipool
                                        function getLaunchBalance() override public pure returns (uint256) {
                                            return 32 ether;
                                        }
                                        /// @notice Returns the value required to pre-launch a minipool
                                        function getPreLaunchValue() override public pure returns (uint256) {
                                            return 1 ether;
                                        }
                                        /// @notice Returns the deposit amount for a given deposit type (only used for legacy minipool types)
                                        function getDepositUserAmount(MinipoolDeposit _depositType) override external pure returns (uint256) {
                                            if (_depositType == MinipoolDeposit.Full) { return getFullDepositUserAmount(); }
                                            if (_depositType == MinipoolDeposit.Half) { return getHalfDepositUserAmount(); }
                                            return 0;
                                        }
                                        /// @notice Returns the user amount for a "Full" deposit minipool
                                        function getFullDepositUserAmount() override public pure returns (uint256) {
                                            return getLaunchBalance() / 2;
                                        }
                                        /// @notice Returns the user amount for a "Half" deposit minipool
                                        function getHalfDepositUserAmount() override public pure returns (uint256) {
                                            return getLaunchBalance() / 2;
                                        }
                                        /// @notice Returns the amount a "Variable" minipool requires to move to staking status
                                        function getVariableDepositAmount() override public pure returns (uint256) {
                                            return getLaunchBalance() - getPreLaunchValue();
                                        }
                                        /// @notice Submit minipool withdrawable events currently enabled (trusted nodes only)
                                        function getSubmitWithdrawableEnabled() override external view returns (bool) {
                                            return getSettingBool("minipool.submit.withdrawable.enabled");
                                        }
                                        /// @notice Returns true if bond reductions are currentl enabled
                                        function getBondReductionEnabled() override external view returns (bool) {
                                            return getSettingBool("minipool.bond.reduction.enabled");
                                        }
                                        /// @notice Returns the timeout period in seconds for prelaunch minipools to launch
                                        function getLaunchTimeout() override external view returns (uint256) {
                                            return getSettingUint("minipool.launch.timeout");
                                        }
                                        /// @notice Returns the maximum number of minipools allowed at one time
                                        function getMaximumCount() override external view returns (uint256) {
                                          return getSettingUint("minipool.maximum.count");
                                        }
                                        /// @notice Returns true if the given time is within the user distribute window
                                        function isWithinUserDistributeWindow(uint256 _time) override external view returns (bool) {
                                            uint256 start = getUserDistributeWindowStart();
                                            uint256 length = getUserDistributeWindowLength();
                                            return (_time >= start && _time < (start + length));
                                        }
                                        /// @notice Returns true if the given time has passed the distribute window
                                        function hasUserDistributeWindowPassed(uint256 _time) override external view returns (bool) {
                                            uint256 start = getUserDistributeWindowStart();
                                            uint256 length = getUserDistributeWindowLength();
                                            return _time >= start + length;
                                        }
                                        /// @notice Returns the start of the user distribute window
                                        function getUserDistributeWindowStart() override public pure returns (uint256) {
                                            return minipoolUserDistributeWindowStart;
                                        }
                                        /// @notice Returns the length of the user distribute window
                                        function getUserDistributeWindowLength() override public view returns (uint256) {
                                            return getSettingUint("minipool.user.distribute.window.length");
                                        }
                                    }