ETH Price: $2,450.00 (+1.89%)

Transaction Decoder

Block:
21241413 at Nov-22-2024 06:14:35 AM +UTC
Transaction Fee:
0.000823790054422881 ETH $2.02
Gas Used:
71,253 Gas / 11.561478877 Gwei

Emitted Events:

464 StateSender.StateSynced( id=2986311, contractAddress=0x8397259c...a11afa28a, data=0x000000000000000000000000B1029AC2BE4E08516697093E2AFEC435057F3511000000000000000000000000594FB75D3DC2DFA0150AD03F99F97817747DD4E10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002469EA17710000000000000000000000000000000000000000000000000F90A38BB1895CDD00000000000000000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x28e4F3a7...189A5bFbE
(Polygon (Matic): State Syncer)
(Titan Builder)
10.452429013029438303 Eth10.452642772029438303 Eth0.000213759
0x9f56F3aE...15477cEC6
0.534404236524696792 Eth
Nonce: 1607
0.533580446470273911 Eth
Nonce: 1608
0.000823790054422881
0xb1029Ac2...5057f3511

Execution Trace

RocketPolygonPriceMessenger.CALL( )
  • RocketStorage.getAddress( _key=7630E125F1C009E5FC974F6DAE77C6D5B1802979B36E6D7145463C21782AF01E ) => ( r=0x6Cc65bF618F55ce2433f9D8d827Fc44117D81399 )
  • RocketNetworkBalances.STATICCALL( )
    • RocketStorage.getUint( _key=5B3A7B8BDDE2122FAD4DC45E51AE0C5CEDC887473A999474F2EAD5A8FAADFE3C ) => ( r=466267399348609521839636 )
    • RocketNetworkBalances.STATICCALL( )
      • RocketStorage.getUint( _key=9DC185B46ED0F11D151F055E45FDE635375A9680C34E501B43A82EB6C09C0951 ) => ( r=522954384182689181242634 )
      • FxRoot.sendMessageToChild( _receiver=0x594Fb75D3dc2DFa0150Ad03F99F97817747dd4E1, _data=0x69EA17710000000000000000000000000000000000000000000000000F90A38BB1895CDD )
        • StateSender.syncState( receiver=0x8397259c983751DAf40400790063935a11afa28a, data=0x000000000000000000000000B1029AC2BE4E08516697093E2AFEC435057F3511000000000000000000000000594FB75D3DC2DFA0150AD03F99F97817747DD4E10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000002469EA17710000000000000000000000000000000000000000000000000F90A38BB1895CDD00000000000000000000000000000000000000000000000000000000 )
          File 1 of 5: RocketPolygonPriceMessenger
          pragma solidity ^0.8.0;
          import {RLPReader} from "./RLPReader.sol";
          library ExitPayloadReader {
              using RLPReader for bytes;
              using RLPReader for RLPReader.RLPItem;
              uint8 constant WORD_SIZE = 32;
              struct ExitPayload {
                  RLPReader.RLPItem[] data;
              }
              struct Receipt {
                  RLPReader.RLPItem[] data;
                  bytes raw;
                  uint256 logIndex;
              }
              struct Log {
                  RLPReader.RLPItem data;
                  RLPReader.RLPItem[] list;
              }
              struct LogTopics {
                  RLPReader.RLPItem[] data;
              }
              // copy paste of private copy() from RLPReader to avoid changing of existing contracts
              function copy(
                  uint256 src,
                  uint256 dest,
                  uint256 len
              ) private pure {
                  if (len == 0) return;
                  // copy as many word sizes as possible
                  for (; len >= WORD_SIZE; len -= WORD_SIZE) {
                      assembly {
                          mstore(dest, mload(src))
                      }
                      src += WORD_SIZE;
                      dest += WORD_SIZE;
                  }
                  if (len == 0) return;
                  // left over bytes. Mask is used to remove unwanted bytes from the word
                  uint256 mask = 256**(WORD_SIZE - len) - 1;
                  assembly {
                      let srcpart := and(mload(src), not(mask)) // zero out src
                      let destpart := and(mload(dest), mask) // retrieve the bytes
                      mstore(dest, or(destpart, srcpart))
                  }
              }
              function toExitPayload(bytes memory data) internal pure returns (ExitPayload memory) {
                  RLPReader.RLPItem[] memory payloadData = data.toRlpItem().toList();
                  return ExitPayload(payloadData);
              }
              function getHeaderNumber(ExitPayload memory payload) internal pure returns (uint256) {
                  return payload.data[0].toUint();
              }
              function getBlockProof(ExitPayload memory payload) internal pure returns (bytes memory) {
                  return payload.data[1].toBytes();
              }
              function getBlockNumber(ExitPayload memory payload) internal pure returns (uint256) {
                  return payload.data[2].toUint();
              }
              function getBlockTime(ExitPayload memory payload) internal pure returns (uint256) {
                  return payload.data[3].toUint();
              }
              function getTxRoot(ExitPayload memory payload) internal pure returns (bytes32) {
                  return bytes32(payload.data[4].toUint());
              }
              function getReceiptRoot(ExitPayload memory payload) internal pure returns (bytes32) {
                  return bytes32(payload.data[5].toUint());
              }
              function getReceipt(ExitPayload memory payload) internal pure returns (Receipt memory receipt) {
                  receipt.raw = payload.data[6].toBytes();
                  RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem();
                  if (receiptItem.isList()) {
                      // legacy tx
                      receipt.data = receiptItem.toList();
                  } else {
                      // pop first byte before parsing receipt
                      bytes memory typedBytes = receipt.raw;
                      bytes memory result = new bytes(typedBytes.length - 1);
                      uint256 srcPtr;
                      uint256 destPtr;
                      assembly {
                          srcPtr := add(33, typedBytes)
                          destPtr := add(0x20, result)
                      }
                      copy(srcPtr, destPtr, result.length);
                      receipt.data = result.toRlpItem().toList();
                  }
                  receipt.logIndex = getReceiptLogIndex(payload);
                  return receipt;
              }
              function getReceiptProof(ExitPayload memory payload) internal pure returns (bytes memory) {
                  return payload.data[7].toBytes();
              }
              function getBranchMaskAsBytes(ExitPayload memory payload) internal pure returns (bytes memory) {
                  return payload.data[8].toBytes();
              }
              function getBranchMaskAsUint(ExitPayload memory payload) internal pure returns (uint256) {
                  return payload.data[8].toUint();
              }
              function getReceiptLogIndex(ExitPayload memory payload) internal pure returns (uint256) {
                  return payload.data[9].toUint();
              }
              // Receipt methods
              function toBytes(Receipt memory receipt) internal pure returns (bytes memory) {
                  return receipt.raw;
              }
              function getLog(Receipt memory receipt) internal pure returns (Log memory) {
                  RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex];
                  return Log(logData, logData.toList());
              }
              // Log methods
              function getEmitter(Log memory log) internal pure returns (address) {
                  return RLPReader.toAddress(log.list[0]);
              }
              function getTopics(Log memory log) internal pure returns (LogTopics memory) {
                  return LogTopics(log.list[1].toList());
              }
              function getData(Log memory log) internal pure returns (bytes memory) {
                  return log.list[2].toBytes();
              }
              function toRlpBytes(Log memory log) internal pure returns (bytes memory) {
                  return log.data.toRlpBytes();
              }
              // LogTopics methods
              function getField(LogTopics memory topics, uint256 index) internal pure returns (RLPReader.RLPItem memory) {
                  return topics.data[index];
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          library Merkle {
              function checkMembership(
                  bytes32 leaf,
                  uint256 index,
                  bytes32 rootHash,
                  bytes memory proof
              ) internal pure returns (bool) {
                  require(proof.length % 32 == 0, "Invalid proof length");
                  uint256 proofHeight = proof.length / 32;
                  // Proof of size n means, height of the tree is n+1.
                  // In a tree of height n+1, max #leafs possible is 2 ^ n
                  require(index < 2**proofHeight, "Leaf index is too big");
                  bytes32 proofElement;
                  bytes32 computedHash = leaf;
                  for (uint256 i = 32; i <= proof.length; i += 32) {
                      assembly {
                          proofElement := mload(add(proof, i))
                      }
                      if (index % 2 == 0) {
                          computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
                      } else {
                          computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
                      }
                      index = index / 2;
                  }
                  return computedHash == rootHash;
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import {RLPReader} from "./RLPReader.sol";
          library MerklePatriciaProof {
              /*
               * @dev Verifies a merkle patricia proof.
               * @param value The terminating value in the trie.
               * @param encodedPath The path in the trie leading to value.
               * @param rlpParentNodes The rlp encoded stack of nodes.
               * @param root The root hash of the trie.
               * @return The boolean validity of the proof.
               */
              function verify(
                  bytes memory value,
                  bytes memory encodedPath,
                  bytes memory rlpParentNodes,
                  bytes32 root
              ) internal pure returns (bool) {
                  RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes);
                  RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item);
                  bytes memory currentNode;
                  RLPReader.RLPItem[] memory currentNodeList;
                  bytes32 nodeKey = root;
                  uint256 pathPtr = 0;
                  bytes memory path = _getNibbleArray(encodedPath);
                  if (path.length == 0) {
                      return false;
                  }
                  for (uint256 i = 0; i < parentNodes.length; i++) {
                      if (pathPtr > path.length) {
                          return false;
                      }
                      currentNode = RLPReader.toRlpBytes(parentNodes[i]);
                      if (nodeKey != keccak256(currentNode)) {
                          return false;
                      }
                      currentNodeList = RLPReader.toList(parentNodes[i]);
                      if (currentNodeList.length == 17) {
                          if (pathPtr == path.length) {
                              if (keccak256(RLPReader.toBytes(currentNodeList[16])) == keccak256(value)) {
                                  return true;
                              } else {
                                  return false;
                              }
                          }
                          uint8 nextPathNibble = uint8(path[pathPtr]);
                          if (nextPathNibble > 16) {
                              return false;
                          }
                          nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[nextPathNibble]));
                          pathPtr += 1;
                      } else if (currentNodeList.length == 2) {
                          uint256 traversed = _nibblesToTraverse(RLPReader.toBytes(currentNodeList[0]), path, pathPtr);
                          if (pathPtr + traversed == path.length) {
                              //leaf node
                              if (keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value)) {
                                  return true;
                              } else {
                                  return false;
                              }
                          }
                          //extension node
                          if (traversed == 0) {
                              return false;
                          }
                          pathPtr += traversed;
                          nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1]));
                      } else {
                          return false;
                      }
                  }
              }
              function _nibblesToTraverse(
                  bytes memory encodedPartialPath,
                  bytes memory path,
                  uint256 pathPtr
              ) private pure returns (uint256) {
                  uint256 len = 0;
                  // encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath
                  // and slicedPath have elements that are each one hex character (1 nibble)
                  bytes memory partialPath = _getNibbleArray(encodedPartialPath);
                  bytes memory slicedPath = new bytes(partialPath.length);
                  // pathPtr counts nibbles in path
                  // partialPath.length is a number of nibbles
                  for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) {
                      bytes1 pathNibble = path[i];
                      slicedPath[i - pathPtr] = pathNibble;
                  }
                  if (keccak256(partialPath) == keccak256(slicedPath)) {
                      len = partialPath.length;
                  } else {
                      len = 0;
                  }
                  return len;
              }
              // bytes b must be hp encoded
              function _getNibbleArray(bytes memory b) internal pure returns (bytes memory) {
                  bytes memory nibbles = "";
                  if (b.length > 0) {
                      uint8 offset;
                      uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b));
                      if (hpNibble == 1 || hpNibble == 3) {
                          nibbles = new bytes(b.length * 2 - 1);
                          bytes1 oddNibble = _getNthNibbleOfBytes(1, b);
                          nibbles[0] = oddNibble;
                          offset = 1;
                      } else {
                          nibbles = new bytes(b.length * 2 - 2);
                          offset = 0;
                      }
                      for (uint256 i = offset; i < nibbles.length; i++) {
                          nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b);
                      }
                  }
                  return nibbles;
              }
              function _getNthNibbleOfBytes(uint256 n, bytes memory str) private pure returns (bytes1) {
                  return bytes1(n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10);
              }
          }
          /*
           * @author Hamdi Allam [email protected]
           * Please reach out with any questions or concerns
           */
          pragma solidity ^0.8.0;
          library RLPReader {
              uint8 constant STRING_SHORT_START = 0x80;
              uint8 constant STRING_LONG_START = 0xb8;
              uint8 constant LIST_SHORT_START = 0xc0;
              uint8 constant LIST_LONG_START = 0xf8;
              uint8 constant WORD_SIZE = 32;
              struct RLPItem {
                  uint256 len;
                  uint256 memPtr;
              }
              struct Iterator {
                  RLPItem item; // Item that's being iterated over.
                  uint256 nextPtr; // Position of the next item in the list.
              }
              /*
               * @dev Returns the next element in the iteration. Reverts if it has not next element.
               * @param self The iterator.
               * @return The next element in the iteration.
               */
              function next(Iterator memory self) internal pure returns (RLPItem memory) {
                  require(hasNext(self));
                  uint256 ptr = self.nextPtr;
                  uint256 itemLength = _itemLength(ptr);
                  self.nextPtr = ptr + itemLength;
                  return RLPItem(itemLength, ptr);
              }
              /*
               * @dev Returns true if the iteration has more elements.
               * @param self The iterator.
               * @return true if the iteration has more elements.
               */
              function hasNext(Iterator memory self) internal pure returns (bool) {
                  RLPItem memory item = self.item;
                  return self.nextPtr < item.memPtr + item.len;
              }
              /*
               * @param item RLP encoded bytes
               */
              function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {
                  uint256 memPtr;
                  assembly {
                      memPtr := add(item, 0x20)
                  }
                  return RLPItem(item.length, memPtr);
              }
              /*
               * @dev Create an iterator. Reverts if item is not a list.
               * @param self The RLP item.
               * @return An 'Iterator' over the item.
               */
              function iterator(RLPItem memory self) internal pure returns (Iterator memory) {
                  require(isList(self));
                  uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);
                  return Iterator(self, ptr);
              }
              /*
               * @param item RLP encoded bytes
               */
              function rlpLen(RLPItem memory item) internal pure returns (uint256) {
                  return item.len;
              }
              /*
               * @param item RLP encoded bytes
               */
              function payloadLen(RLPItem memory item) internal pure returns (uint256) {
                  return item.len - _payloadOffset(item.memPtr);
              }
              /*
               * @param item RLP encoded list in bytes
               */
              function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {
                  require(isList(item));
                  uint256 items = numItems(item);
                  RLPItem[] memory result = new RLPItem[](items);
                  uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);
                  uint256 dataLen;
                  for (uint256 i = 0; i < items; i++) {
                      dataLen = _itemLength(memPtr);
                      result[i] = RLPItem(dataLen, memPtr);
                      memPtr = memPtr + dataLen;
                  }
                  return result;
              }
              // @return indicator whether encoded payload is a list. negate this function call for isData.
              function isList(RLPItem memory item) internal pure returns (bool) {
                  if (item.len == 0) return false;
                  uint8 byte0;
                  uint256 memPtr = item.memPtr;
                  assembly {
                      byte0 := byte(0, mload(memPtr))
                  }
                  if (byte0 < LIST_SHORT_START) return false;
                  return true;
              }
              /*
               * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory.
               * @return keccak256 hash of RLP encoded bytes.
               */
              function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) {
                  uint256 ptr = item.memPtr;
                  uint256 len = item.len;
                  bytes32 result;
                  assembly {
                      result := keccak256(ptr, len)
                  }
                  return result;
              }
              function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) {
                  uint256 offset = _payloadOffset(item.memPtr);
                  uint256 memPtr = item.memPtr + offset;
                  uint256 len = item.len - offset; // data length
                  return (memPtr, len);
              }
              /*
               * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory.
               * @return keccak256 hash of the item payload.
               */
              function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) {
                  (uint256 memPtr, uint256 len) = payloadLocation(item);
                  bytes32 result;
                  assembly {
                      result := keccak256(memPtr, len)
                  }
                  return result;
              }
              /** RLPItem conversions into data types **/
              // @returns raw rlp encoding in bytes
              function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) {
                  bytes memory result = new bytes(item.len);
                  if (result.length == 0) return result;
                  uint256 ptr;
                  assembly {
                      ptr := add(0x20, result)
                  }
                  copy(item.memPtr, ptr, item.len);
                  return result;
              }
              // any non-zero byte < 128 is considered true
              function toBoolean(RLPItem memory item) internal pure returns (bool) {
                  require(item.len == 1);
                  uint256 result;
                  uint256 memPtr = item.memPtr;
                  assembly {
                      result := byte(0, mload(memPtr))
                  }
                  return result == 0 ? false : true;
              }
              function toAddress(RLPItem memory item) internal pure returns (address) {
                  // 1 byte for the length prefix
                  require(item.len == 21);
                  return address(uint160(toUint(item)));
              }
              function toUint(RLPItem memory item) internal pure returns (uint256) {
                  require(item.len > 0 && item.len <= 33);
                  uint256 offset = _payloadOffset(item.memPtr);
                  uint256 len = item.len - offset;
                  uint256 result;
                  uint256 memPtr = item.memPtr + offset;
                  assembly {
                      result := mload(memPtr)
                      // shift to the correct location if neccesary
                      if lt(len, 32) {
                          result := div(result, exp(256, sub(32, len)))
                      }
                  }
                  return result;
              }
              // enforces 32 byte length
              function toUintStrict(RLPItem memory item) internal pure returns (uint256) {
                  // one byte prefix
                  require(item.len == 33);
                  uint256 result;
                  uint256 memPtr = item.memPtr + 1;
                  assembly {
                      result := mload(memPtr)
                  }
                  return result;
              }
              function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
                  require(item.len > 0);
                  uint256 offset = _payloadOffset(item.memPtr);
                  uint256 len = item.len - offset; // data length
                  bytes memory result = new bytes(len);
                  uint256 destPtr;
                  assembly {
                      destPtr := add(0x20, result)
                  }
                  copy(item.memPtr + offset, destPtr, len);
                  return result;
              }
              /*
               * Private Helpers
               */
              // @return number of payload items inside an encoded list.
              function numItems(RLPItem memory item) private pure returns (uint256) {
                  if (item.len == 0) return 0;
                  uint256 count = 0;
                  uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);
                  uint256 endPtr = item.memPtr + item.len;
                  while (currPtr < endPtr) {
                      currPtr = currPtr + _itemLength(currPtr); // skip over an item
                      count++;
                  }
                  return count;
              }
              // @return entire rlp item byte length
              function _itemLength(uint256 memPtr) private pure returns (uint256) {
                  uint256 itemLen;
                  uint256 byte0;
                  assembly {
                      byte0 := byte(0, mload(memPtr))
                  }
                  if (byte0 < STRING_SHORT_START) itemLen = 1;
                  else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1;
                  else if (byte0 < LIST_SHORT_START) {
                      assembly {
                          let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is
                          memPtr := add(memPtr, 1) // skip over the first byte
                          /* 32 byte word size */
                          let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len
                          itemLen := add(dataLen, add(byteLen, 1))
                      }
                  } else if (byte0 < LIST_LONG_START) {
                      itemLen = byte0 - LIST_SHORT_START + 1;
                  } else {
                      assembly {
                          let byteLen := sub(byte0, 0xf7)
                          memPtr := add(memPtr, 1)
                          let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length
                          itemLen := add(dataLen, add(byteLen, 1))
                      }
                  }
                  return itemLen;
              }
              // @return number of bytes until the data
              function _payloadOffset(uint256 memPtr) private pure returns (uint256) {
                  uint256 byte0;
                  assembly {
                      byte0 := byte(0, mload(memPtr))
                  }
                  if (byte0 < STRING_SHORT_START) return 0;
                  else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1;
                  else if (byte0 < LIST_SHORT_START)
                      // being explicit
                      return byte0 - (STRING_LONG_START - 1) + 1;
                  else return byte0 - (LIST_LONG_START - 1) + 1;
              }
              /*
               * @param src Pointer to source
               * @param dest Pointer to destination
               * @param len Amount of memory to copy from the source
               */
              function copy(
                  uint256 src,
                  uint256 dest,
                  uint256 len
              ) private pure {
                  if (len == 0) return;
                  // copy as many word sizes as possible
                  for (; len >= WORD_SIZE; len -= WORD_SIZE) {
                      assembly {
                          mstore(dest, mload(src))
                      }
                      src += WORD_SIZE;
                      dest += WORD_SIZE;
                  }
                  if (len == 0) return;
                  // left over bytes. Mask is used to remove unwanted bytes from the word
                  uint256 mask = 256**(WORD_SIZE - len) - 1;
                  assembly {
                      let srcpart := and(mload(src), not(mask)) // zero out src
                      let destpart := and(mload(dest), mask) // retrieve the bytes
                      mstore(dest, or(destpart, srcpart))
                  }
              }
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          // IFxMessageProcessor represents interface to process message
          interface IFxMessageProcessor {
              function processMessageFromRoot(
                  uint256 stateId,
                  address rootMessageSender,
                  bytes calldata data
              ) external;
          }
          /**
           * @notice Mock child tunnel contract to receive and send message from L2
           */
          abstract contract FxBaseChildTunnel is IFxMessageProcessor {
              // MessageTunnel on L1 will get data from this event
              event MessageSent(bytes message);
              // fx child
              address public fxChild;
              // fx root tunnel
              address public fxRootTunnel;
              constructor(address _fxChild) {
                  fxChild = _fxChild;
              }
              // Sender must be fxRootTunnel in case of ERC20 tunnel
              modifier validateSender(address sender) {
                  require(sender == fxRootTunnel, "FxBaseChildTunnel: INVALID_SENDER_FROM_ROOT");
                  _;
              }
              // set fxRootTunnel if not set already
              function setFxRootTunnel(address _fxRootTunnel) external virtual {
                  require(fxRootTunnel == address(0x0), "FxBaseChildTunnel: ROOT_TUNNEL_ALREADY_SET");
                  fxRootTunnel = _fxRootTunnel;
              }
              function processMessageFromRoot(
                  uint256 stateId,
                  address rootMessageSender,
                  bytes calldata data
              ) external override {
                  require(msg.sender == fxChild, "FxBaseChildTunnel: INVALID_SENDER");
                  _processMessageFromRoot(stateId, rootMessageSender, data);
              }
              /**
               * @notice Emit message that can be received on Root Tunnel
               * @dev Call the internal function when need to emit message
               * @param message bytes message that will be sent to Root Tunnel
               * some message examples -
               *   abi.encode(tokenId);
               *   abi.encode(tokenId, tokenMetadata);
               *   abi.encode(messageType, messageData);
               */
              function _sendMessageToRoot(bytes memory message) internal {
                  emit MessageSent(message);
              }
              /**
               * @notice Process message received from Root Tunnel
               * @dev function needs to be implemented to handle message as per requirement
               * This is called by onStateReceive function.
               * Since it is called via a system call, any event will not be emitted during its execution.
               * @param stateId unique state id
               * @param sender root message sender
               * @param message bytes message that was sent from Root Tunnel
               */
              function _processMessageFromRoot(
                  uint256 stateId,
                  address sender,
                  bytes memory message
              ) internal virtual;
          }
          // SPDX-License-Identifier: MIT
          pragma solidity ^0.8.0;
          import {RLPReader} from "../lib/RLPReader.sol";
          import {MerklePatriciaProof} from "../lib/MerklePatriciaProof.sol";
          import {Merkle} from "../lib/Merkle.sol";
          import "../lib/ExitPayloadReader.sol";
          interface IFxStateSender {
              function sendMessageToChild(address _receiver, bytes calldata _data) external;
          }
          contract ICheckpointManager {
              struct HeaderBlock {
                  bytes32 root;
                  uint256 start;
                  uint256 end;
                  uint256 createdAt;
                  address proposer;
              }
              /**
               * @notice mapping of checkpoint header numbers to block details
               * @dev These checkpoints are submited by plasma contracts
               */
              mapping(uint256 => HeaderBlock) public headerBlocks;
          }
          abstract contract FxBaseRootTunnel {
              using RLPReader for RLPReader.RLPItem;
              using Merkle for bytes32;
              using ExitPayloadReader for bytes;
              using ExitPayloadReader for ExitPayloadReader.ExitPayload;
              using ExitPayloadReader for ExitPayloadReader.Log;
              using ExitPayloadReader for ExitPayloadReader.LogTopics;
              using ExitPayloadReader for ExitPayloadReader.Receipt;
              // keccak256(MessageSent(bytes))
              bytes32 public constant SEND_MESSAGE_EVENT_SIG = 0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036;
              // state sender contract
              IFxStateSender public fxRoot;
              // root chain manager
              ICheckpointManager public checkpointManager;
              // child tunnel contract which receives and sends messages
              address public fxChildTunnel;
              // storage to avoid duplicate exits
              mapping(bytes32 => bool) public processedExits;
              constructor(address _checkpointManager, address _fxRoot) {
                  checkpointManager = ICheckpointManager(_checkpointManager);
                  fxRoot = IFxStateSender(_fxRoot);
              }
              // set fxChildTunnel if not set already
              function setFxChildTunnel(address _fxChildTunnel) public virtual {
                  require(fxChildTunnel == address(0x0), "FxBaseRootTunnel: CHILD_TUNNEL_ALREADY_SET");
                  fxChildTunnel = _fxChildTunnel;
              }
              /**
               * @notice Send bytes message to Child Tunnel
               * @param message bytes message that will be sent to Child Tunnel
               * some message examples -
               *   abi.encode(tokenId);
               *   abi.encode(tokenId, tokenMetadata);
               *   abi.encode(messageType, messageData);
               */
              function _sendMessageToChild(bytes memory message) internal {
                  fxRoot.sendMessageToChild(fxChildTunnel, message);
              }
              function _validateAndExtractMessage(bytes memory inputData) internal returns (bytes memory) {
                  ExitPayloadReader.ExitPayload memory payload = inputData.toExitPayload();
                  bytes memory branchMaskBytes = payload.getBranchMaskAsBytes();
                  uint256 blockNumber = payload.getBlockNumber();
                  // checking if exit has already been processed
                  // unique exit is identified using hash of (blockNumber, branchMask, receiptLogIndex)
                  bytes32 exitHash = keccak256(
                      abi.encodePacked(
                          blockNumber,
                          // first 2 nibbles are dropped while generating nibble array
                          // this allows branch masks that are valid but bypass exitHash check (changing first 2 nibbles only)
                          // so converting to nibble array and then hashing it
                          MerklePatriciaProof._getNibbleArray(branchMaskBytes),
                          payload.getReceiptLogIndex()
                      )
                  );
                  require(processedExits[exitHash] == false, "FxRootTunnel: EXIT_ALREADY_PROCESSED");
                  processedExits[exitHash] = true;
                  ExitPayloadReader.Receipt memory receipt = payload.getReceipt();
                  ExitPayloadReader.Log memory log = receipt.getLog();
                  // check child tunnel
                  require(fxChildTunnel == log.getEmitter(), "FxRootTunnel: INVALID_FX_CHILD_TUNNEL");
                  bytes32 receiptRoot = payload.getReceiptRoot();
                  // verify receipt inclusion
                  require(
                      MerklePatriciaProof.verify(receipt.toBytes(), branchMaskBytes, payload.getReceiptProof(), receiptRoot),
                      "FxRootTunnel: INVALID_RECEIPT_PROOF"
                  );
                  // verify checkpoint inclusion
                  _checkBlockMembershipInCheckpoint(
                      blockNumber,
                      payload.getBlockTime(),
                      payload.getTxRoot(),
                      receiptRoot,
                      payload.getHeaderNumber(),
                      payload.getBlockProof()
                  );
                  ExitPayloadReader.LogTopics memory topics = log.getTopics();
                  require(
                      bytes32(topics.getField(0).toUint()) == SEND_MESSAGE_EVENT_SIG, // topic0 is event sig
                      "FxRootTunnel: INVALID_SIGNATURE"
                  );
                  // received message data
                  bytes memory message = abi.decode(log.getData(), (bytes)); // event decodes params again, so decoding bytes to get message
                  return message;
              }
              function _checkBlockMembershipInCheckpoint(
                  uint256 blockNumber,
                  uint256 blockTime,
                  bytes32 txRoot,
                  bytes32 receiptRoot,
                  uint256 headerNumber,
                  bytes memory blockProof
              ) private view {
                  (bytes32 headerRoot, uint256 startBlock, , uint256 createdAt, ) = checkpointManager.headerBlocks(headerNumber);
                  require(
                      keccak256(abi.encodePacked(blockNumber, blockTime, txRoot, receiptRoot)).checkMembership(
                          blockNumber - startBlock,
                          headerRoot,
                          blockProof
                      ),
                      "FxRootTunnel: INVALID_HEADER"
                  );
              }
              /**
               * @notice receive message from  L2 to L1, validated by proof
               * @dev This function verifies if the transaction actually happened on child chain
               *
               * @param inputData RLP encoded data of the reference tx containing following list of fields
               *  0 - headerNumber - Checkpoint header block number containing the reference tx
               *  1 - blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root
               *  2 - blockNumber - Block number containing the reference tx on child chain
               *  3 - blockTime - Reference tx block time
               *  4 - txRoot - Transactions root of block
               *  5 - receiptRoot - Receipts root of block
               *  6 - receipt - Receipt of the reference transaction
               *  7 - receiptProof - Merkle proof of the reference receipt
               *  8 - branchMask - 32 bits denoting the path of receipt in merkle tree
               *  9 - receiptLogIndex - Log Index to read from the receipt
               */
              function receiveMessage(bytes memory inputData) public virtual {
                  bytes memory message = _validateAndExtractMessage(inputData);
                  _processMessageFromChild(message);
              }
              /**
               * @notice Process message received from Child Tunnel
               * @dev function needs to be implemented to handle message as per requirement
               * This is called by receiveMessage function.
               * Since it is called via a system call, any event will not be emitted during its execution.
               * @param message bytes message that was sent from Child Tunnel
               */
              function _processMessageFromChild(bytes memory message) internal virtual;
          }
          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;
          }
          pragma solidity >0.5.0 <0.9.0;
          // 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;
          }
          // SPDX-License-Identifier: GPL-3.0
          pragma solidity ^0.8.13;
          import "@fx-portal/tunnel/FxBaseRootTunnel.sol";
          import "rocketpool/contracts/interface/network/RocketNetworkBalancesInterface.sol";
          import "rocketpool/contracts/interface/RocketStorageInterface.sol";
          /// @author Kane Wallmann (Rocket Pool)
          /// @notice Retrieves the rETH exchange rate from Rocket Pool and submits it to the oracle contract on Polygon
          contract RocketPolygonPriceMessenger is FxBaseRootTunnel {
              // Immutables
              RocketStorageInterface immutable rocketStorage;
              bytes32 immutable rocketNetworkBalancesKey;
              /// @notice The most recently submitted rate
              uint256 lastRate;
              constructor(RocketStorageInterface _rocketStorage, address _checkpointManager, address _fxRoot) FxBaseRootTunnel(_checkpointManager, _fxRoot) {
                  rocketStorage = _rocketStorage;
                  // Precompute storage key for RocketNetworkBalances address
                  rocketNetworkBalancesKey = keccak256(abi.encodePacked("contract.address", "rocketNetworkBalances"));
              }
              /// @notice Not used
              function _processMessageFromChild(bytes memory data) internal override {
                  revert();
              }
              /// @notice Returns whether the rate has changed since it was last submitted
              function rateStale() external view returns (bool) {
                  return rate() != lastRate;
              }
              /// @notice Returns the calculated rETH exchange rate
              function rate() public view returns (uint256) {
                  // Retrieve the inputs from RocketNetworkBalances and calculate the rate
                  RocketNetworkBalancesInterface rocketNetworkBalances = RocketNetworkBalancesInterface(rocketStorage.getAddress(rocketNetworkBalancesKey));
                  uint256 supply = rocketNetworkBalances.getTotalRETHSupply();
                  if (supply == 0) {
                      return 0;
                  }
                  return 1 ether * rocketNetworkBalances.getTotalETHBalance() / supply;
              }
              /// @notice Submits the current rETH exchange rate to the L2 contract
              function submitRate() external {
                  lastRate = rate();
                  // Send the cross chain message
                  bytes memory data = abi.encodeWithSignature('updateRate(uint256)', lastRate);
                  _sendMessageToChild(data);
              }
          }
          // SPDX-License-Identifier: GPL-3.0
          pragma solidity ^0.8.13;
          import "@fx-portal/tunnel/FxBaseChildTunnel.sol";
          /// @author Kane Wallmann (Rocket Pool)
          /// @notice Receives updates from L1 on the canonical rETH exchange rate
          contract RocketPolygonPriceOracle is FxBaseChildTunnel {
              // Events
              event RateUpdated(uint256 rate);
              /// @notice The rETH exchange rate in the form of how much ETH 1 rETH is worth
              uint256 public rate;
              /// @notice The timestamp of the block in which the rate was last updated
              uint256 public lastUpdated;
              constructor(address _fxChild) FxBaseChildTunnel(_fxChild) {
              }
              /// @notice Processes an incoming message from L1
              function _processMessageFromRoot(
                  uint256 stateId,
                  address sender,
                  bytes memory data
              ) internal override validateSender(sender) {
                  // Execute the transaction on self
                  (bool success, ) = address(this).call(data);
                  require(success, "Failed to execute transaction on child");
              }
              /// @notice Called by the messenger contract on L1 to update the exchange rate
              function updateRate(uint256 _newRate) external {
                  // Only allow calls from self
                  require(msg.sender == address(this));
                  // Update state
                  rate = _newRate;
                  lastUpdated = block.timestamp;
                  // Emit event
                  emit RateUpdated(_newRate);
              }
          }
          

          File 2 of 5: StateSender
          /**
          Matic network contracts
          */
          
          pragma solidity ^0.5.2;
          
          
          contract Ownable {
              address private _owner;
          
              event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor () internal {
                  _owner = msg.sender;
                  emit OwnershipTransferred(address(0), _owner);
              }
          
              /**
               * @return the address of the owner.
               */
              function owner() public view returns (address) {
                  return _owner;
              }
          
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                  require(isOwner());
                  _;
              }
          
              /**
               * @return true if `msg.sender` is the owner of the contract.
               */
              function isOwner() public view returns (bool) {
                  return msg.sender == _owner;
              }
          
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               * @notice Renouncing ownership will leave the contract without an owner,
               * thereby removing any functionality that is only available to the owner.
               */
              function renounceOwnership() public onlyOwner {
                  emit OwnershipTransferred(_owner, address(0));
                  _owner = address(0);
              }
          
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                  _transferOwnership(newOwner);
              }
          
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address newOwner) internal {
                  require(newOwner != address(0));
                  emit OwnershipTransferred(_owner, newOwner);
                  _owner = newOwner;
              }
          }
          
          library SafeMath {
              /**
               * @dev Multiplies two unsigned integers, reverts on overflow.
               */
              function mul(uint256 a, uint256 b) internal pure returns (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-solidity/pull/522
                  if (a == 0) {
                      return 0;
                  }
          
                  uint256 c = a * b;
                  require(c / a == b);
          
                  return c;
              }
          
              /**
               * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
               */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  // Solidity only automatically asserts when dividing by 0
                  require(b > 0);
                  uint256 c = a / b;
                  // assert(a == b * c + a % b); // There is no case in which this doesn't hold
          
                  return c;
              }
          
              /**
               * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a);
                  uint256 c = a - b;
          
                  return c;
              }
          
              /**
               * @dev Adds two unsigned integers, reverts on overflow.
               */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a);
          
                  return c;
              }
          
              /**
               * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
               * reverts when dividing by zero.
               */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b != 0);
                  return a % b;
              }
          }
          
          contract StateSender is Ownable {
              using SafeMath for uint256;
          
              uint256 public counter;
              mapping(address => address) public registrations;
          
              event NewRegistration(
                  address indexed user,
                  address indexed sender,
                  address indexed receiver
              );
              event RegistrationUpdated(
                  address indexed user,
                  address indexed sender,
                  address indexed receiver
              );
              event StateSynced(
                  uint256 indexed id,
                  address indexed contractAddress,
                  bytes data
              );
          
              modifier onlyRegistered(address receiver) {
                  require(registrations[receiver] == msg.sender, "Invalid sender");
                  _;
              }
          
              function syncState(address receiver, bytes calldata data)
                  external
                  onlyRegistered(receiver)
              {
                  counter = counter.add(1);
                  emit StateSynced(counter, receiver, data);
              }
          
              // register new contract for state sync
              function register(address sender, address receiver) public {
                  require(
                      isOwner() || registrations[receiver] == msg.sender,
                      "StateSender.register: Not authorized to register"
                  );
                  registrations[receiver] = sender;
                  if (registrations[receiver] == address(0)) {
                      emit NewRegistration(msg.sender, sender, receiver);
                  } else {
                      emit RegistrationUpdated(msg.sender, sender, receiver);
                  }
              }
          }

          File 3 of 5: RocketStorage
          // SPDX-License-Identifier: MIT
          pragma solidity >=0.6.0 <0.8.0;
          /**
           * @dev Wrappers over Solidity's arithmetic operations with added overflow
           * checks.
           *
           * Arithmetic operations in Solidity wrap on overflow. This can easily result
           * in bugs, because programmers usually assume that an overflow raises an
           * error, which is the standard behavior in high level programming languages.
           * `SafeMath` restores this intuition by reverting the transaction when an
           * operation overflows.
           *
           * Using this library instead of the unchecked operations eliminates an entire
           * class of bugs, so it's recommended to use it always.
           */
          library SafeMath {
              /**
               * @dev Returns the addition of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  uint256 c = a + b;
                  if (c < a) return (false, 0);
                  return (true, c);
              }
              /**
               * @dev Returns the substraction of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b > a) return (false, 0);
                  return (true, a - b);
              }
              /**
               * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
               *
               * _Available since v3.4._
               */
              function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                  // benefit is lost if 'b' is also tested.
                  // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                  if (a == 0) return (true, 0);
                  uint256 c = a * b;
                  if (c / a != b) return (false, 0);
                  return (true, c);
              }
              /**
               * @dev Returns the division of two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a / b);
              }
              /**
               * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
               *
               * _Available since v3.4._
               */
              function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                  if (b == 0) return (false, 0);
                  return (true, a % b);
              }
              /**
               * @dev Returns the addition of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `+` operator.
               *
               * Requirements:
               *
               * - Addition cannot overflow.
               */
              function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  require(c >= a, "SafeMath: addition overflow");
                  return c;
              }
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting on
               * overflow (when the result is negative).
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b <= a, "SafeMath: subtraction overflow");
                  return a - b;
              }
              /**
               * @dev Returns the multiplication of two unsigned integers, reverting on
               * overflow.
               *
               * Counterpart to Solidity's `*` operator.
               *
               * Requirements:
               *
               * - Multiplication cannot overflow.
               */
              function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                  if (a == 0) return 0;
                  uint256 c = a * b;
                  require(c / a == b, "SafeMath: multiplication overflow");
                  return c;
              }
              /**
               * @dev Returns the integer division of two unsigned integers, reverting on
               * division by zero. The result is rounded towards zero.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: division by zero");
                  return a / b;
              }
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting when dividing by zero.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                  require(b > 0, "SafeMath: modulo by zero");
                  return a % b;
              }
              /**
               * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
               * overflow (when the result is negative).
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {trySub}.
               *
               * Counterpart to Solidity's `-` operator.
               *
               * Requirements:
               *
               * - Subtraction cannot overflow.
               */
              function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b <= a, errorMessage);
                  return a - b;
              }
              /**
               * @dev Returns the integer division of two unsigned integers, reverting with custom message on
               * division by zero. The result is rounded towards zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryDiv}.
               *
               * Counterpart to Solidity's `/` operator. Note: this function uses a
               * `revert` opcode (which leaves remaining gas untouched) while Solidity
               * uses an invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a / b;
              }
              /**
               * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
               * reverting with custom message when dividing by zero.
               *
               * CAUTION: This function is deprecated because it requires allocating memory for the error
               * message unnecessarily. For custom revert reasons use {tryMod}.
               *
               * Counterpart to Solidity's `%` operator. This function uses a `revert`
               * opcode (which leaves remaining gas untouched) while Solidity uses an
               * invalid opcode to revert (consuming all remaining gas).
               *
               * Requirements:
               *
               * - The divisor cannot be zero.
               */
              function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                  require(b > 0, errorMessage);
                  return a % b;
              }
          }
          /**
            *       .
            *      / \\
            *     |.'.|
            *     |'.'|
            *   ,'|   |`.
            *  |,-'-|-'-.|
            *   __|_| |         _        _      _____           _
            *  | ___ \\|        | |      | |    | ___ \\         | |
            *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
            *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
            *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
            *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
            * +---------------------------------------------------+
            * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
            * +---------------------------------------------------+
            *
            *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
            *  be community-owned, decentralised, and trustless.
            *
            *  For more information about Rocket Pool, visit https://rocketpool.net
            *
            *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
            *
            */
          pragma solidity 0.7.6;
          // SPDX-License-Identifier: GPL-3.0-only
          import "../interface/RocketStorageInterface.sol";
          import "@openzeppelin/contracts/math/SafeMath.sol";
          /// @title The primary persistent storage for Rocket Pool
          /// @author David Rugendyke
          contract RocketStorage is RocketStorageInterface {
              // Events
              event NodeWithdrawalAddressSet(address indexed node, address indexed withdrawalAddress, uint256 time);
              event GuardianChanged(address oldGuardian, address newGuardian);
              // Libraries
              using SafeMath for uint256;
              // Storage maps
              mapping(bytes32 => string)     private stringStorage;
              mapping(bytes32 => bytes)      private bytesStorage;
              mapping(bytes32 => uint256)    private uintStorage;
              mapping(bytes32 => int256)     private intStorage;
              mapping(bytes32 => address)    private addressStorage;
              mapping(bytes32 => bool)       private booleanStorage;
              mapping(bytes32 => bytes32)    private bytes32Storage;
              // Protected storage (not accessible by network contracts)
              mapping(address => address)    private withdrawalAddresses;
              mapping(address => address)    private pendingWithdrawalAddresses;
              // Guardian address
              address guardian;
              address newGuardian;
              // Flag storage has been initialised
              bool storageInit = false;
              /// @dev Only allow access from the latest version of a contract in the Rocket Pool network after deployment
              modifier onlyLatestRocketNetworkContract() {
                  if (storageInit == true) {
                      // Make sure the access is permitted to only contracts in our Dapp
                      require(booleanStorage[keccak256(abi.encodePacked("contract.exists", msg.sender))], "Invalid or outdated network contract");
                  } else {
                      // Only Dapp and the guardian account are allowed access during initialisation.
                      // tx.origin is only safe to use in this case for deployment since no external contracts are interacted with
                      require((
                          booleanStorage[keccak256(abi.encodePacked("contract.exists", msg.sender))] || tx.origin == guardian
                      ), "Invalid or outdated network contract attempting access during deployment");
                  }
                  _;
              }
              /// @dev Construct RocketStorage
              constructor() {
                  // Set the guardian upon deployment
                  guardian = msg.sender;
              }
              // Get guardian address
              function getGuardian() external override view returns (address) {
                  return guardian;
              }
              // Transfers guardianship to a new address
              function setGuardian(address _newAddress) external override {
                  // Check tx comes from current guardian
                  require(msg.sender == guardian, "Is not guardian account");
                  // Store new address awaiting confirmation
                  newGuardian = _newAddress;
              }
              // Confirms change of guardian
              function confirmGuardian() external override {
                  // Check tx came from new guardian address
                  require(msg.sender == newGuardian, "Confirmation must come from new guardian address");
                  // Store old guardian for event
                  address oldGuardian = guardian;
                  // Update guardian and clear storage
                  guardian = newGuardian;
                  delete newGuardian;
                  // Emit event
                  emit GuardianChanged(oldGuardian, guardian);
              }
              // Set this as being deployed now
              function getDeployedStatus() external override view returns (bool) {
                  return storageInit;
              }
              // Set this as being deployed now
              function setDeployedStatus() external {
                  // Only guardian can lock this down
                  require(msg.sender == guardian, "Is not guardian account");
                  // Set it now
                  storageInit = true;
              }
              // Protected storage
              // Get a node's withdrawal address
              function getNodeWithdrawalAddress(address _nodeAddress) public override view returns (address) {
                  // If no withdrawal address has been set, return the nodes address
                  address withdrawalAddress = withdrawalAddresses[_nodeAddress];
                  if (withdrawalAddress == address(0)) {
                      return _nodeAddress;
                  }
                  return withdrawalAddress;
              }
              // Get a node's pending withdrawal address
              function getNodePendingWithdrawalAddress(address _nodeAddress) external override view returns (address) {
                  return pendingWithdrawalAddresses[_nodeAddress];
              }
              // Set a node's withdrawal address
              function setWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress, bool _confirm) external override {
                  // Check new withdrawal address
                  require(_newWithdrawalAddress != address(0x0), "Invalid withdrawal address");
                  // Confirm the transaction is from the node's current withdrawal address
                  address withdrawalAddress = getNodeWithdrawalAddress(_nodeAddress);
                  require(withdrawalAddress == msg.sender, "Only a tx from a node's withdrawal address can update it");
                  // Update immediately if confirmed
                  if (_confirm) {
                      updateWithdrawalAddress(_nodeAddress, _newWithdrawalAddress);
                  }
                  // Set pending withdrawal address if not confirmed
                  else {
                      pendingWithdrawalAddresses[_nodeAddress] = _newWithdrawalAddress;
                  }
              }
              // Confirm a node's new withdrawal address
              function confirmWithdrawalAddress(address _nodeAddress) external override {
                  // Get node by pending withdrawal address
                  require(pendingWithdrawalAddresses[_nodeAddress] == msg.sender, "Confirmation must come from the pending withdrawal address");
                  delete pendingWithdrawalAddresses[_nodeAddress];
                  // Update withdrawal address
                  updateWithdrawalAddress(_nodeAddress, msg.sender);
              }
              // Update a node's withdrawal address
              function updateWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress) private {
                  // Set new withdrawal address
                  withdrawalAddresses[_nodeAddress] = _newWithdrawalAddress;
                  // Emit withdrawal address set event
                  emit NodeWithdrawalAddressSet(_nodeAddress, _newWithdrawalAddress, block.timestamp);
              }
              /// @param _key The key for the record
              function getAddress(bytes32 _key) override external view returns (address r) {
                  return addressStorage[_key];
              }
              /// @param _key The key for the record
              function getUint(bytes32 _key) override external view returns (uint256 r) {
                  return uintStorage[_key];
              }
              /// @param _key The key for the record
              function getString(bytes32 _key) override external view returns (string memory) {
                  return stringStorage[_key];
              }
              /// @param _key The key for the record
              function getBytes(bytes32 _key) override external view returns (bytes memory) {
                  return bytesStorage[_key];
              }
              /// @param _key The key for the record
              function getBool(bytes32 _key) override external view returns (bool r) {
                  return booleanStorage[_key];
              }
              /// @param _key The key for the record
              function getInt(bytes32 _key) override external view returns (int r) {
                  return intStorage[_key];
              }
              /// @param _key The key for the record
              function getBytes32(bytes32 _key) override external view returns (bytes32 r) {
                  return bytes32Storage[_key];
              }
              /// @param _key The key for the record
              function setAddress(bytes32 _key, address _value) onlyLatestRocketNetworkContract override external {
                  addressStorage[_key] = _value;
              }
              /// @param _key The key for the record
              function setUint(bytes32 _key, uint _value) onlyLatestRocketNetworkContract override external {
                  uintStorage[_key] = _value;
              }
              /// @param _key The key for the record
              function setString(bytes32 _key, string calldata _value) onlyLatestRocketNetworkContract override external {
                  stringStorage[_key] = _value;
              }
              /// @param _key The key for the record
              function setBytes(bytes32 _key, bytes calldata _value) onlyLatestRocketNetworkContract override external {
                  bytesStorage[_key] = _value;
              }
              /// @param _key The key for the record
              function setBool(bytes32 _key, bool _value) onlyLatestRocketNetworkContract override external {
                  booleanStorage[_key] = _value;
              }
              /// @param _key The key for the record
              function setInt(bytes32 _key, int _value) onlyLatestRocketNetworkContract override external {
                  intStorage[_key] = _value;
              }
              /// @param _key The key for the record
              function setBytes32(bytes32 _key, bytes32 _value) onlyLatestRocketNetworkContract override external {
                  bytes32Storage[_key] = _value;
              }
              /// @param _key The key for the record
              function deleteAddress(bytes32 _key) onlyLatestRocketNetworkContract override external {
                  delete addressStorage[_key];
              }
              /// @param _key The key for the record
              function deleteUint(bytes32 _key) onlyLatestRocketNetworkContract override external {
                  delete uintStorage[_key];
              }
              /// @param _key The key for the record
              function deleteString(bytes32 _key) onlyLatestRocketNetworkContract override external {
                  delete stringStorage[_key];
              }
              /// @param _key The key for the record
              function deleteBytes(bytes32 _key) onlyLatestRocketNetworkContract override external {
                  delete bytesStorage[_key];
              }
              /// @param _key The key for the record
              function deleteBool(bytes32 _key) onlyLatestRocketNetworkContract override external {
                  delete booleanStorage[_key];
              }
              /// @param _key The key for the record
              function deleteInt(bytes32 _key) onlyLatestRocketNetworkContract override external {
                  delete intStorage[_key];
              }
              /// @param _key The key for the record
              function deleteBytes32(bytes32 _key) onlyLatestRocketNetworkContract override external {
                  delete bytes32Storage[_key];
              }
              /// @param _key The key for the record
              /// @param _amount An amount to add to the record's value
              function addUint(bytes32 _key, uint256 _amount) onlyLatestRocketNetworkContract override external {
                  uintStorage[_key] = uintStorage[_key].add(_amount);
              }
              /// @param _key The key for the record
              /// @param _amount An amount to subtract from the record's value
              function subUint(bytes32 _key, uint256 _amount) onlyLatestRocketNetworkContract override external {
                  uintStorage[_key] = uintStorage[_key].sub(_amount);
              }
          }
          /**
            *       .
            *      / \\
            *     |.'.|
            *     |'.'|
            *   ,'|   |`.
            *  |,-'-|-'-.|
            *   __|_| |         _        _      _____           _
            *  | ___ \\|        | |      | |    | ___ \\         | |
            *  | |_/ /|__   ___| | _____| |_   | |_/ /__   ___ | |
            *  |    // _ \\ / __| |/ / _ \\ __|  |  __/ _ \\ / _ \\| |
            *  | |\\ \\ (_) | (__|   <  __/ |_   | | | (_) | (_) | |
            *  \\_| \\_\\___/ \\___|_|\\_\\___|\\__|  \\_|  \\___/ \\___/|_|
            * +---------------------------------------------------+
            * |    DECENTRALISED STAKING PROTOCOL FOR ETHEREUM    |
            * +---------------------------------------------------+
            *
            *  Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
            *  be community-owned, decentralised, and trustless.
            *
            *  For more information about Rocket Pool, visit https://rocketpool.net
            *
            *  Authors: David Rugendyke, Jake Pospischil, Kane Wallmann, Darren Langley, Joe Clapis, Nick Doherty
            *
            */
          pragma solidity 0.7.6;
          // SPDX-License-Identifier: GPL-3.0-only
          interface RocketStorageInterface {
              // Deploy status
              function getDeployedStatus() external view returns (bool);
              // Guardian
              function getGuardian() external view returns(address);
              function setGuardian(address _newAddress) external;
              function confirmGuardian() external;
              // Getters
              function getAddress(bytes32 _key) external view returns (address);
              function getUint(bytes32 _key) external view returns (uint);
              function getString(bytes32 _key) external view returns (string memory);
              function getBytes(bytes32 _key) external view returns (bytes memory);
              function getBool(bytes32 _key) external view returns (bool);
              function getInt(bytes32 _key) external view returns (int);
              function getBytes32(bytes32 _key) external view returns (bytes32);
              // Setters
              function setAddress(bytes32 _key, address _value) external;
              function setUint(bytes32 _key, uint _value) external;
              function setString(bytes32 _key, string calldata _value) external;
              function setBytes(bytes32 _key, bytes calldata _value) external;
              function setBool(bytes32 _key, bool _value) external;
              function setInt(bytes32 _key, int _value) external;
              function setBytes32(bytes32 _key, bytes32 _value) external;
              // Deleters
              function deleteAddress(bytes32 _key) external;
              function deleteUint(bytes32 _key) external;
              function deleteString(bytes32 _key) external;
              function deleteBytes(bytes32 _key) external;
              function deleteBool(bytes32 _key) external;
              function deleteInt(bytes32 _key) external;
              function deleteBytes32(bytes32 _key) external;
              // Arithmetic
              function addUint(bytes32 _key, uint256 _amount) external;
              function subUint(bytes32 _key, uint256 _amount) external;
              // Protected storage
              function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
              function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
              function setWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress, bool _confirm) external;
              function confirmWithdrawalAddress(address _nodeAddress) external;
          }
          

          File 4 of 5: 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 5 of 5: FxRoot
          // SPDX-License-Identifier: MIT
          pragma solidity 0.7.3;
          
          
          interface IStateSender {
              function syncState(address receiver, bytes calldata data) external;
          }
          
          interface IFxStateSender {
              function sendMessageToChild(address _receiver, bytes calldata _data) external;
          }
          
          /** 
           * @title FxRoot root contract for fx-portal
           */
          contract FxRoot is IFxStateSender {
              IStateSender public stateSender;
              address public fxChild;
          
              constructor(address _stateSender) {
                  stateSender = IStateSender(_stateSender);
              }
          
              function setFxChild(address _fxChild) public {
                  require(fxChild == address(0x0));
                  fxChild = _fxChild;
              }
          
              function sendMessageToChild(address _receiver, bytes calldata _data) public override {
                  bytes memory data = abi.encode(msg.sender, _receiver, _data);
                  stateSender.syncState(fxChild, data);
              }
          }