diff --git a/src/_zkapauthorizer/_storage_server.py b/src/_zkapauthorizer/_storage_server.py
index e54f3780787bf500937188b512411cc3b027e074..da6c959cb4bc3bd22b7c48e1fb5fdbb3cf7a71cb 100644
--- a/src/_zkapauthorizer/_storage_server.py
+++ b/src/_zkapauthorizer/_storage_server.py
@@ -31,11 +31,10 @@ from os.path import join
 from struct import calcsize, unpack
 
 import attr
-from allmydata.interfaces import RIStorageServer
+from allmydata.interfaces import RIStorageServer, TestAndWriteVectorsForShares
 from allmydata.storage.common import storage_index_to_dir
-from allmydata.storage.immutable import ShareFile
 from allmydata.storage.lease import LeaseInfo
-from allmydata.storage.mutable import MutableShareFile
+from allmydata.storage.server import StorageServer
 from allmydata.storage.shares import get_share_file
 from allmydata.util.base32 import b2a
 from attr.validators import instance_of, provides
@@ -60,6 +59,11 @@ from .storage_common import (
     slot_testv_and_readv_and_writev_message,
 )
 
+try:
+    from typing import Dict, List, Optional
+except ImportError:
+    pass
+
 # See allmydata/storage/mutable.py
 SLOT_HEADER_SIZE = 468
 LEASE_TRAILER_SIZE = 4
@@ -755,7 +759,7 @@ def share_has_active_leases(storage_server, storage_index, sharenum, now):
 
 
 def get_writev_price(storage_server, pass_value, storage_index, tw_vectors, now):
-    # type: (StorageServer, int, bytes, TestWriteVectors, float) -> int
+    # type: (StorageServer, int, bytes, TestAndWriteVectorsForShares, float) -> int
     """
     Determine the price to execute the given test/write vectors.
     """
diff --git a/src/_zkapauthorizer/lease_maintenance.py b/src/_zkapauthorizer/lease_maintenance.py
index ad901881175186407b9d442318d6be2e051b2f6b..da19a99ab563202541467e88939c562b2f0cc9ec 100644
--- a/src/_zkapauthorizer/lease_maintenance.py
+++ b/src/_zkapauthorizer/lease_maintenance.py
@@ -36,8 +36,14 @@ from twisted.python.log import err
 from zope.interface import implementer
 
 from .controller import bracket
+from .foolscap import ShareStat
 from .model import ILeaseMaintenanceObserver
 
+try:
+    from typing import Iterable
+except ImportError:
+    pass
+
 SERVICE_NAME = u"lease maintenance service"
 
 
diff --git a/src/_zkapauthorizer/tests/test_lease_maintenance.py b/src/_zkapauthorizer/tests/test_lease_maintenance.py
index a5af5299757b943b8fe46161957d59b0972b51c9..49278eae88f42a190c3e5e9f85b8c389697fa286 100644
--- a/src/_zkapauthorizer/tests/test_lease_maintenance.py
+++ b/src/_zkapauthorizer/tests/test_lease_maintenance.py
@@ -37,7 +37,6 @@ from hypothesis.strategies import (
     lists,
     randoms,
     sets,
-    tuples,
 )
 from testtools import TestCase
 from testtools.matchers import (
@@ -51,7 +50,7 @@ from testtools.matchers import (
 )
 from testtools.twistedsupport import succeeded
 from twisted.application.service import IService
-from twisted.internet.defer import maybeDeferred, succeed
+from twisted.internet.defer import Deferred, maybeDeferred, succeed
 from twisted.internet.task import Clock
 from twisted.python.filepath import FilePath
 from zope.interface import implementer
@@ -80,8 +79,30 @@ from .strategies import (
     storage_indexes,
 )
 
+try:
+    from typing import Dict, List
+except ImportError:
+    pass
+
+
 default_lease_maint_config = lease_maintenance_from_tahoe_config(empty_config)
 
+def interval_means():
+    return floats(
+        # It doesn't make sense to have a negative check interval mean.
+        min_value=0,
+        # We can't make this value too large or it isn't convertable to a
+        # timedelta.  Also, even values as large as this one are of
+        # questionable value.
+        max_value=60 * 60 * 24 * 365,
+    ).map(
+        # By representing the result as a timedelta we avoid the cases where
+        # the lower precision of timedelta compared to float drops the whole
+        # value (anything between 0 and 1 microsecond).  This is just one
+        # example of how working with timedeltas is nicer, in general.
+        lambda s: timedelta(seconds=s),
+    )
+
 
 def dummy_maintain_leases():
     pass
@@ -477,7 +498,6 @@ def lists_of_buckets():
             min_size=count,
             max_size=count,
         )
-        expiration_strategy = lists
         return builds(
             zip,
             si_strategy,
diff --git a/src/_zkapauthorizer/tests/test_storage_protocol.py b/src/_zkapauthorizer/tests/test_storage_protocol.py
index 6e3fd1222470ab0959d8f936177c1f1d78ba68d0..82b62acbdab9f855efc5cd83503252f07627627a 100644
--- a/src/_zkapauthorizer/tests/test_storage_protocol.py
+++ b/src/_zkapauthorizer/tests/test_storage_protocol.py
@@ -46,7 +46,6 @@ from twisted.internet.task import Clock
 from twisted.python.filepath import FilePath
 from twisted.python.runtime import platform
 
-from .._storage_client import _encode_passes
 from ..api import (
     MorePassesRequired,
     ZKAPAuthorizerStorageClient,
@@ -57,7 +56,6 @@ from ..storage_common import (
     allocate_buckets_message,
     get_implied_data_length,
     required_passes,
-    slot_testv_and_readv_and_writev_message,
 )
 from .common import skipIf
 from .fixtures import AnonymousStorageServer
diff --git a/src/_zkapauthorizer/tests/test_storage_server.py b/src/_zkapauthorizer/tests/test_storage_server.py
index cdff293f8e7cd638f7b4cb3df1263196584061d5..cd0eb20d52e70db098875fa6a9ea48c4b26deb5c 100644
--- a/src/_zkapauthorizer/tests/test_storage_server.py
+++ b/src/_zkapauthorizer/tests/test_storage_server.py
@@ -383,26 +383,22 @@ class PassValidationTests(TestCase):
             ),
         )
 
-    def _test_lease_operation_fails_without_passes(
-        self,
-        storage_index,
-        secrets,
-        sharenums,
-        allocated_size,
-        lease_operation,
-        lease_operation_message,
+    @given(
+        storage_index=storage_indexes(),
+        secrets=tuples(
+            lease_renew_secrets(),
+            lease_cancel_secrets(),
+        ),
+        sharenums=sharenum_sets(),
+        allocated_size=sizes(),
+    )
+    def test_add_lease_fails_without_passes(
+        self, storage_index, secrets, sharenums, allocated_size
     ):
         """
-        Assert that a lease-taking operation fails if it is not supplied with
-        enough passes to cover the cost of the lease.
-
-        :param lease_operation: A two-argument callable.  It is called with a
-            storage server and a list of passes.  It should perform the
-            lease-taking operation.
-
-        :param lease_operation_message: A one-argument callable.  It is called
-            with a storage index.  It should return the ZKAPAuthorizer binding
-            message for the lease-taking operation.
+        If ``remote_add_lease`` is invoked without supplying enough passes to
+        cover the storage for all shares on the given storage index, the
+        operation fails with ``MorePassesRequired``.
         """
         renew_secret, cancel_secret = secrets
 
@@ -433,11 +429,20 @@ class PassValidationTests(TestCase):
         # Attempt the lease operation with one fewer pass than is required.
         passes = make_passes(
             self.signing_key,
-            lease_operation_message(storage_index),
+            add_lease_message(storage_index),
             list(RandomToken.create() for i in range(required_count - 1)),
         )
         try:
-            result = lease_operation(self.storage_server, passes)
+            result = self.storage_server.doRemoteCall(
+                "add_lease",
+                (
+                    passes,
+                    storage_index,
+                    renew_secret,
+                    cancel_secret,
+                ),
+                {},
+            )
         except MorePassesRequired as e:
             self.assertThat(
                 e,
@@ -452,46 +457,6 @@ class PassValidationTests(TestCase):
         else:
             self.fail("Expected MorePassesRequired, got {}".format(result))
 
-    @given(
-        storage_index=storage_indexes(),
-        secrets=tuples(
-            lease_renew_secrets(),
-            lease_cancel_secrets(),
-        ),
-        sharenums=sharenum_sets(),
-        allocated_size=sizes(),
-    )
-    def test_add_lease_fails_without_passes(
-        self, storage_index, secrets, sharenums, allocated_size
-    ):
-        """
-        If ``remote_add_lease`` is invoked without supplying enough passes to
-        cover the storage for all shares on the given storage index, the
-        operation fails with ``MorePassesRequired``.
-        """
-        renew_secret, cancel_secret = secrets
-
-        def add_lease(storage_server, passes):
-            return storage_server.doRemoteCall(
-                "add_lease",
-                (
-                    passes,
-                    storage_index,
-                    renew_secret,
-                    cancel_secret,
-                ),
-                {},
-            )
-
-        return self._test_lease_operation_fails_without_passes(
-            storage_index,
-            secrets,
-            sharenums,
-            allocated_size,
-            add_lease,
-            add_lease_message,
-        )
-
     @given(
         slot=storage_indexes(),
         secrets=tuples(
diff --git a/tests.nix b/tests.nix
index b8b5b39b0d656f43d07cd5c66938c7f52a28bdd2..7023c06a296dfd5be2cb3468c789d7038ac25add 100644
--- a/tests.nix
+++ b/tests.nix
@@ -49,7 +49,7 @@ in
       mkdir -p $out
 
       pushd ${zkapauthorizer.src}
-      ${python}/bin/pyflakes
+      ${python}/bin/pyflakes src
       ${lint-python}/bin/black --check src
       ${lint-python}/bin/isort --check src
       popd