func: function rootOwnerOf(uint256 _tokenId) public view returns (bytes32 rootOwner) {
          address rootOwnerAddress = tokenIdToTokenOwner[_tokenId].tokenOwner;
          require(rootOwnerAddress != address(0));
          uint256 parentTokenId = tokenIdToTokenOwner[_tokenId].parentTokenId;
          bool isParent = parentTokenId > 0;
          if (isParent) {
              parentTokenId--;
          }
  
          if((rootOwnerAddress == address(this))) {
              do {
                  if(isParent == false) {
                      
                      
                      return ERC998_MAGIC_VALUE << 224 | bytes32(rootOwnerAddress);
                  }
                  else {
                      
                      (rootOwnerAddress, parentTokenId, isParent) = _tokenOwnerOf(parentTokenId);
                  }
              } while(rootOwnerAddress == address(this));
              _tokenId = parentTokenId;
          }
  
          bytes memory calldata;
          bool callSuccess;
  
          if (isParent == false) {
  
              
              
              calldata = abi.encodeWithSelector(0xed81cdda, address(this), _tokenId);
              assembly {
                  callSuccess := staticcall(gas, rootOwnerAddress, add(calldata, 0x20), mload(calldata), calldata, 0x20)
                  if callSuccess {
                      rootOwner := mload(calldata)
                  }
              }
              if(callSuccess == true && rootOwner >> 224 == ERC998_MAGIC_VALUE) {
                  
                  return rootOwner;
              }
              else {
                  
                  
                  
                  return ERC998_MAGIC_VALUE << 224 | bytes32(rootOwnerAddress);
              }
          }
          else {
  
              
              calldata = abi.encodeWithSelector(0x43a61a8e, parentTokenId);
              assembly {
                  callSuccess := staticcall(gas, rootOwnerAddress, add(calldata, 0x20), mload(calldata), calldata, 0x20)
                  if callSuccess {
                      rootOwner := mload(calldata)
                  }
              }
              if (callSuccess == true && rootOwner >> 224 == ERC998_MAGIC_VALUE) {
                  
                  
                  
                  return rootOwner;
              }
              else {
                  
                  address childContract = rootOwnerAddress;
                  
                  calldata = abi.encodeWithSelector(0x6352211e, parentTokenId);
                  assembly {
                      callSuccess := staticcall(gas, rootOwnerAddress, add(calldata, 0x20), mload(calldata), calldata, 0x20)
                      if callSuccess {
                          rootOwnerAddress := mload(calldata)
                      }
                  }
                  require(callSuccess);
  
                  
                  calldata = abi.encodeWithSelector(0xed81cdda, childContract, parentTokenId);
                  assembly {
                      callSuccess := staticcall(gas, rootOwnerAddress, add(calldata, 0x20), mload(calldata), calldata, 0x20)
                      if callSuccess {
                          rootOwner := mload(calldata)
                      }
                  }
                  if(callSuccess == true && rootOwner >> 224 == ERC998_MAGIC_VALUE) {
                      
                      return rootOwner;
                  }
                  else {
                      
                      
                      
                      return ERC998_MAGIC_VALUE << 224 | bytes32(rootOwnerAddress);
                  }
              }
          }
      }