diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,8 @@
 # Changelog
 
+- 0.1.1 (2025-01-06)
+  * Includes a minor encoding-related performance optimisation.
+
 - 0.1.0 (2024-12-18)
   * Initial release, supporting basic encoding/decoding.
 
diff --git a/lib/Data/ByteString/Base58.hs b/lib/Data/ByteString/Base58.hs
--- a/lib/Data/ByteString/Base58.hs
+++ b/lib/Data/ByteString/Base58.hs
@@ -19,6 +19,7 @@
 import qualified Data.Bits as B
 import Data.Bits ((.|.))
 import qualified Data.ByteString as BS
+import qualified Data.ByteString.Unsafe as BU
 
 fi :: (Integral a, Num b) => a -> b
 fi = fromIntegral
@@ -74,6 +75,15 @@
       | h == 0x31 -> go (BS.cons 0x00 acc) t
       | otherwise -> acc
 
+-- to base256
+unroll_base256 :: Integer -> BS.ByteString
+unroll_base256 = BS.reverse . BS.unfoldr coalg where
+  coalg a
+    | a == 0 = Nothing
+    | otherwise = Just $
+        let (b, c) = quotRem a 256
+        in  (fi c, b)
+
 -- from base256
 roll_base256 :: BS.ByteString -> Integer
 roll_base256 = BS.foldl' alg 0 where
@@ -86,7 +96,7 @@
     | a == 0 = Nothing
     | otherwise = Just $
         let (b, c) = quotRem a 58
-        in  (BS.index base58_charset (fi c), b)
+        in  (BU.unsafeIndex base58_charset (fi c), b)
 
 -- from base58
 roll_base58 :: BS.ByteString -> Integer
@@ -95,13 +105,4 @@
     Just w -> b * 58 + fi w
     Nothing ->
       error "ppad-base58 (roll_base58): not a base58-encoded bytestring"
-
--- to base256
-unroll_base256 :: Integer -> BS.ByteString
-unroll_base256 = BS.reverse . BS.unfoldr coalg where
-  coalg a
-    | a == 0 = Nothing
-    | otherwise = Just $
-        let (b, c) = quotRem a 256
-        in  (fi c, b)
 
diff --git a/ppad-base58.cabal b/ppad-base58.cabal
--- a/ppad-base58.cabal
+++ b/ppad-base58.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               ppad-base58
-version:            0.1.0
+version:            0.1.1
 synopsis:           base58 and base58check encoding/decoding.
 license:            MIT
 license-file:       LICENSE
@@ -47,6 +47,7 @@
     , ppad-base58
     , tasty
     , tasty-hunit
+    , tasty-quickcheck
     , text
 
 benchmark base58-bench
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -12,8 +12,10 @@
 import qualified Data.ByteString.Base58Check as B58Check
 import qualified Data.Text.Encoding as TE
 import qualified Data.Text.IO as TIO
+import Data.Word (Word8)
 import Test.Tasty
 import Test.Tasty.HUnit
+import qualified Test.Tasty.QuickCheck as Q
 
 data Valid_Base58Check = Valid_Base58Check {
     vc_string  :: !BS.ByteString
@@ -78,6 +80,40 @@
   let enc = B58.encode vb_decodedHex
   assertEqual mempty enc vb_encoded
 
+newtype BS = BS BS.ByteString
+  deriving (Eq, Show)
+
+bytes :: Int -> Q.Gen BS.ByteString
+bytes k = do
+  l <- Q.chooseInt (0, k)
+  v <- Q.vectorOf l Q.arbitrary
+  pure (BS.pack v)
+
+data B58C = B58C Word8 BS
+  deriving (Eq, Show)
+
+instance Q.Arbitrary BS where
+  arbitrary = do
+    b <- bytes 1024
+    pure (BS b)
+
+instance Q.Arbitrary B58C where
+  arbitrary = do
+    w8 <- Q.arbitrary
+    bs <- Q.arbitrary
+    pure (B58C w8 bs)
+
+base58_decode_inverts_encode :: BS -> Bool
+base58_decode_inverts_encode (BS bs) = case B58.decode (B58.encode bs) of
+  Nothing -> False
+  Just b  -> b == bs
+
+base58check_decode_inverts_encode :: B58C -> Bool
+base58check_decode_inverts_encode (B58C w8 (BS bs)) =
+  case B58Check.decode (B58Check.encode w8 bs) of
+    Nothing -> False
+    Just (w8', bs') -> w8 == w8' && bs == bs'
+
 main :: IO ()
 main = do
   scure_base58 <- TIO.readFile "etc/base58.json"
@@ -89,7 +125,15 @@
   case per of
     Nothing -> error "couldn't parse vectors"
     Just (b58, b58c) -> defaultMain $ testGroup "ppad-base58" [
-        testGroup "base58" (fmap execute_base58 b58)
-      , execute_base58check b58c
+        testGroup "unit tests" [
+            testGroup "base58" (fmap execute_base58 b58)
+          , execute_base58check b58c
+          ]
+      , testGroup "property tests" [
+          Q.testProperty "(base58) decode . encode ~ id" $
+            Q.withMaxSuccess 250 base58_decode_inverts_encode
+        , Q.testProperty "(base58check) decode . encode ~ id" $
+            Q.withMaxSuccess 250 base58check_decode_inverts_encode
+        ]
       ]
 
