diff --git a/gnss-converters.cabal b/gnss-converters.cabal
--- a/gnss-converters.cabal
+++ b/gnss-converters.cabal
@@ -1,5 +1,5 @@
 name: gnss-converters
-version: 0.3.10
+version: 0.3.11
 cabal-version: >=1.22
 build-type: Simple
 license: BSD3
@@ -35,8 +35,8 @@
         monad-control >=1.0.1.0,
         mtl >=2.2.1,
         resourcet >=1.1.9,
-        rtcm >=0.2.2,
-        sbp >=2.2.11,
+        rtcm >=0.2.5,
+        sbp >=2.2.12,
         time >=1.5.0.1,
         transformers-base >=0.4.4,
         vector >=0.11.0.0
@@ -52,8 +52,7 @@
         binary-conduit >=1.2.4.1,
         conduit >=1.2.10,
         conduit-extra >=1.1.16,
-        gnss-converters,
-        resourcet >=1.1.9
+        gnss-converters
     default-language: Haskell2010
     hs-source-dirs: main
     ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
@@ -66,8 +65,7 @@
         binary-conduit >=1.2.4.1,
         conduit >=1.2.10,
         conduit-extra >=1.1.16,
-        gnss-converters,
-        resourcet >=1.1.9
+        gnss-converters
     default-language: Haskell2010
     hs-source-dirs: main
     ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
@@ -88,8 +86,8 @@
         gnss-converters,
         lens >=4.13,
         resourcet >=1.1.9,
-        rtcm >=0.2.2,
-        sbp >=2.2.11,
+        rtcm >=0.2.5,
+        sbp >=2.2.12,
         tasty >=0.11.2.1,
         tasty-golden >=2.3.1.1,
         tasty-hunit >=0.9.2,
diff --git a/main/RTCM32SBP.hs b/main/RTCM32SBP.hs
--- a/main/RTCM32SBP.hs
+++ b/main/RTCM32SBP.hs
@@ -11,7 +11,6 @@
 -- RTCM3 to SBP tool.
 
 import BasicPrelude
-import Control.Monad.Trans.Resource
 import Data.Conduit
 import Data.Conduit.Binary
 import Data.Conduit.Serialization.Binary
@@ -22,9 +21,9 @@
 main :: IO ()
 main = do
   s <- newStore
-  runResourceT $ runConvertT s $
-    sourceHandle stdin     =$=
-    conduitDecode          =$=
-    awaitForever converter =$=
-    conduitEncode          $$
-    sinkHandle stdout
+  runConvertT s $ runConduitRes $
+    sourceHandle stdin
+      =$= conduitDecode
+      =$= awaitForever converter
+      =$= conduitEncode
+      $$  sinkHandle stdout
diff --git a/main/SBP2RTCM3.hs b/main/SBP2RTCM3.hs
--- a/main/SBP2RTCM3.hs
+++ b/main/SBP2RTCM3.hs
@@ -11,7 +11,6 @@
 -- SBP to RTCM3 tool.
 
 import BasicPrelude
-import Control.Monad.Trans.Resource
 import Data.Conduit
 import Data.Conduit.Binary
 import Data.Conduit.Serialization.Binary
@@ -20,9 +19,9 @@
 
 main :: IO ()
 main =
-  runResourceT $
-    sourceHandle stdin     =$=
-    conduitDecode          =$=
-    awaitForever converter =$=
-    conduitEncode          $$
-    sinkHandle stdout
+  runConduitRes $
+    sourceHandle stdin
+      =$= conduitDecode
+      =$= awaitForever converter
+      =$= conduitEncode
+      $$   sinkHandle stdout
diff --git a/src/Data/RTCM3/SBP/Ephemerides.hs b/src/Data/RTCM3/SBP/Ephemerides.hs
--- a/src/Data/RTCM3/SBP/Ephemerides.hs
+++ b/src/Data/RTCM3/SBP/Ephemerides.hs
@@ -32,7 +32,7 @@
 toGpsTimeSec :: MonadIO m => Word16 -> Word16 -> m GpsTimeSec
 toGpsTimeSec wn tow = do
   wn' <- view gpsTimeNano_wn <$> currentGpsTime
-  return GpsTimeSec
+  pure GpsTimeSec
     { _gpsTimeSec_tow = 16 * fromIntegral tow
     , _gpsTimeSec_wn  = wn' `shiftR` 10 `shiftL` 10 + wn
     }
@@ -78,7 +78,7 @@
 toGpsEphemerisCommonContent :: MonadIO m => Msg1019 -> m EphemerisCommonContent
 toGpsEphemerisCommonContent m = do
   toe <- toGpsTimeSec (m ^. msg1019_ephemeris ^. gpsEphemeris_wn) (m ^. msg1019_ephemeris ^. gpsEphemeris_toe)
-  return EphemerisCommonContent
+  pure EphemerisCommonContent
     { _ephemerisCommonContent_sid = GnssSignal16
       { _gnssSignal16_sat  = m ^. msg1019_header ^. gpsEphemerisHeader_sat
       , _gnssSignal16_code = 0 -- there is an L2P status flag in msg 1019, but I don't think that applies
diff --git a/src/Data/RTCM3/SBP/Observations.hs b/src/Data/RTCM3/SBP/Observations.hs
--- a/src/Data/RTCM3/SBP/Observations.hs
+++ b/src/Data/RTCM3/SBP/Observations.hs
@@ -35,7 +35,7 @@
   x      <- liftIO $ readIORef ref
   (y, z) <- f x
   liftIO $ writeIORef ref y
-  return z
+  pure z
 
 -- | Update and convert stored and incoming GPS times.
 --
@@ -43,9 +43,9 @@
 toGpsTimeNano station rollover = do
   timeMap <- view storeGpsTimeMap
   modifyIORefM timeMap $ \timeMap' -> do
-    t <- maybe currentGpsTime return (timeMap' ^. at station)
+    t <- maybe currentGpsTime pure (timeMap' ^. at station)
     let t' = rollover t
-    return (timeMap' & at station ?~ t', (t, t'))
+    pure (timeMap' & at station ?~ t', (t, t'))
 
 -- | Default observation doppler.
 --
diff --git a/src/Data/RTCM3/SBP/Time.hs b/src/Data/RTCM3/SBP/Time.hs
--- a/src/Data/RTCM3/SBP/Time.hs
+++ b/src/Data/RTCM3/SBP/Time.hs
@@ -90,7 +90,7 @@
 currentGpsTime :: MonadIO m => m GpsTimeNano
 currentGpsTime = do
   t <- liftIO $ addUTCTime (fromIntegral gpsLeapSeconds) <$> getCurrentTime
-  return $ GpsTimeNano (toTow t) 0 (toWn t)
+  pure $ GpsTimeNano (toTow t) 0 (toWn t)
 
 -- | Update GPS time based on GPS time of week, handling week rollover.
 --
diff --git a/src/Data/RTCM3/SBP/Types.hs b/src/Data/RTCM3/SBP/Types.hs
--- a/src/Data/RTCM3/SBP/Types.hs
+++ b/src/Data/RTCM3/SBP/Types.hs
@@ -43,32 +43,29 @@
 
 newtype ConvertT e m a = ConvertT { unConvertT :: ReaderT e m a }
   deriving
-    ( Functor
-    , Applicative
-    , Monad
-    , MonadIO
-    , MonadTrans
-    )
-
-instance MonadThrow m => MonadThrow (ConvertT r m) where
-    throwM = lift . throwM
+    ( Functor, Applicative, Monad, MonadIO, MonadTrans, MonadThrow, MonadReader e )
 
 instance MonadResource m => MonadResource (ConvertT r m) where
   liftResourceT = lift . liftResourceT
+  {-# INLINE liftResourceT #-}
 
-instance Monad m => MonadReader e (ConvertT e m) where
-    ask     = ConvertT ask
-    local f = ConvertT . local f . unConvertT
-    reader  = ConvertT . reader
+instance MonadBaseControl b m => MonadBaseControl b (ConvertT r m) where
+  type StM (ConvertT r m) a = ComposeSt (ConvertT r) m a
+  liftBaseWith = defaultLiftBaseWith
+  {-# INLINE liftBaseWith #-}
+  restoreM = defaultRestoreM
+  {-# INLINE restoreM #-}
 
 instance MonadTransControl (ConvertT r) where
-    type StT (ConvertT r) a = StT (ReaderT r) a
-
-    liftWith = defaultLiftWith ConvertT unConvertT
-    restoreT = defaultRestoreT ConvertT
+  type StT (ConvertT r) a = StT (ReaderT r) a
+  liftWith = defaultLiftWith ConvertT unConvertT
+  {-# INLINE liftWith #-}
+  restoreT = defaultRestoreT ConvertT
+  {-# INLINE restoreT #-}
 
 instance MonadBase b m => MonadBase b (ConvertT r m) where
-    liftBase = liftBaseDefault
+  liftBase = liftBaseDefault
+  {-# INLINE liftBase #-}
 
 data Store = Store
   { _storeGpsTimeMap   :: IORef GpsTimeNanoMap
diff --git a/src/SwiftNav/SBP/RTCM3.hs b/src/SwiftNav/SBP/RTCM3.hs
--- a/src/SwiftNav/SBP/RTCM3.hs
+++ b/src/SwiftNav/SBP/RTCM3.hs
@@ -22,4 +22,4 @@
 
 converter :: Monad m => SBPMsg -> Conduit i m [RTCM3Msg]
 converter = \case
-  _sbpMsg -> return mempty
+  _sbpMsg -> pure mempty
