diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt b/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt
index 9e01cc916f..11ec5119b5 100644
--- a/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt
+++ b/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt
@@ -517,11 +517,7 @@ class InterestRateSwap() : Contract {
             override val clauses = listOf(Agree(), Fix(), Pay(), Mature())
         }
 
-        class Timestamped : SingleClause {
-            override val ifMatched = MatchBehaviour.CONTINUE
-            override val ifNotMatched = MatchBehaviour.ERROR
-            override val requiredCommands = emptySet<Class<out CommandData>>()
-
+        class Timestamped : SingleClause() {
             override fun verify(tx: TransactionForContract, commands: Collection<AuthenticatedObject<CommandData>>): Set<CommandData> {
                 require(tx.timestamp?.midpoint != null) { "must be timestamped" }
                 // We return an empty set because we don't process any commands
diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/asset/Obligation.kt b/contracts/src/main/kotlin/com/r3corda/contracts/asset/Obligation.kt
index 53ab2e2cb5..c0e4fad216 100644
--- a/contracts/src/main/kotlin/com/r3corda/contracts/asset/Obligation.kt
+++ b/contracts/src/main/kotlin/com/r3corda/contracts/asset/Obligation.kt
@@ -197,11 +197,7 @@ class Obligation<P> : Contract {
          * any lifecycle change clause, which is the only clause that involve
          * non-standard lifecycle states on input/output.
          */
-        class VerifyLifecycle<P> : SingleClause, GroupClause<State<P>, Issued<Terms<P>>> {
-            override val requiredCommands: Set<Class<out CommandData>> = emptySet()
-            override val ifMatched: MatchBehaviour = MatchBehaviour.CONTINUE
-            override val ifNotMatched: MatchBehaviour = MatchBehaviour.ERROR
-
+        class VerifyLifecycle<P> : SingleClause(), GroupClause<State<P>, Issued<Terms<P>>> {
             override fun verify(tx: TransactionForContract, commands: Collection<AuthenticatedObject<CommandData>>): Set<CommandData>
                 = verify(
                     tx.inputs.filterIsInstance<State<P>>(),
diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/clause/Net.kt b/contracts/src/main/kotlin/com/r3corda/contracts/clause/Net.kt
index cca285f51c..5566aa38a9 100644
--- a/contracts/src/main/kotlin/com/r3corda/contracts/clause/Net.kt
+++ b/contracts/src/main/kotlin/com/r3corda/contracts/clause/Net.kt
@@ -43,13 +43,10 @@ data class MultilateralNetState<P>(
  * Clause for netting contract states. Currently only supports obligation contract.
  */
 // TODO: Make this usable for any nettable contract states
-open class NetClause<P> : SingleClause {
-    override val ifNotMatched: MatchBehaviour
-        get() = MatchBehaviour.CONTINUE
-    override val ifMatched: MatchBehaviour
-        get() = MatchBehaviour.END
-    override val requiredCommands: Set<Class<out CommandData>>
-        get() = setOf(Obligation.Commands.Net::class.java)
+open class NetClause<P> : SingleClause() {
+    override val ifMatched: MatchBehaviour = MatchBehaviour.END
+    override val ifNotMatched: MatchBehaviour = MatchBehaviour.CONTINUE
+    override val requiredCommands: Set<Class<out CommandData>> = setOf(Obligation.Commands.Net::class.java)
 
     @Suppress("ConvertLambdaToReference")
     override fun verify(tx: TransactionForContract, commands: Collection<AuthenticatedObject<CommandData>>): Set<CommandData> {
diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt
index 69e0195de2..8305ffcda7 100644
--- a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt
+++ b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt
@@ -218,11 +218,7 @@ interface LinearState: ContractState {
     /**
      * Standard clause to verify the LinearState safety properties.
      */
-    class ClauseVerifier<S: LinearState>(val stateClass: Class<S>) : SingleClause {
-        override val ifMatched = MatchBehaviour.CONTINUE
-        override val ifNotMatched = MatchBehaviour.ERROR
-        override val requiredCommands = emptySet<Class<out CommandData>>()
-
+    class ClauseVerifier<S: LinearState>(val stateClass: Class<S>) : SingleClause() {
         override fun verify(tx: TransactionForContract, commands: Collection<AuthenticatedObject<CommandData>>): Set<CommandData> {
             val inputs = tx.inputs.filterIsInstance(stateClass)
             val inputIds = inputs.map { it.linearId }.distinct()
diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/clauses/Clause.kt b/core/src/main/kotlin/com/r3corda/core/contracts/clauses/Clause.kt
index 1c61161efa..b7b542525a 100644
--- a/core/src/main/kotlin/com/r3corda/core/contracts/clauses/Clause.kt
+++ b/core/src/main/kotlin/com/r3corda/core/contracts/clauses/Clause.kt
@@ -41,4 +41,12 @@ interface SingleVerify {
 
 }
 
-interface SingleClause : Clause, SingleVerify
\ No newline at end of file
+/**
+ * A single verifiable clause. By default always matches, continues to the next clause when matched and errors
+ * if not matched.
+ */
+abstract class SingleClause : Clause, SingleVerify {
+    override val ifMatched: MatchBehaviour = MatchBehaviour.CONTINUE
+    override val ifNotMatched: MatchBehaviour = MatchBehaviour.ERROR
+    override val requiredCommands: Set<Class<out CommandData>> = emptySet()
+}
\ No newline at end of file
diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/clauses/ClauseVerifier.kt b/core/src/main/kotlin/com/r3corda/core/contracts/clauses/ClauseVerifier.kt
index d734fcd43f..eaa4331c3d 100644
--- a/core/src/main/kotlin/com/r3corda/core/contracts/clauses/ClauseVerifier.kt
+++ b/core/src/main/kotlin/com/r3corda/core/contracts/clauses/ClauseVerifier.kt
@@ -27,7 +27,7 @@ fun verifyClauses(tx: TransactionForContract,
         }
 
         when (matchBehaviour) {
-            MatchBehaviour.ERROR -> throw IllegalStateException()
+            MatchBehaviour.ERROR -> throw IllegalStateException("Error due to matching/not matching ${clause}")
             MatchBehaviour.CONTINUE -> {
             }
             MatchBehaviour.END -> break@verify
diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/clauses/GroupClauseVerifier.kt b/core/src/main/kotlin/com/r3corda/core/contracts/clauses/GroupClauseVerifier.kt
index 3478fe8027..cf1b4a2007 100644
--- a/core/src/main/kotlin/com/r3corda/core/contracts/clauses/GroupClauseVerifier.kt
+++ b/core/src/main/kotlin/com/r3corda/core/contracts/clauses/GroupClauseVerifier.kt
@@ -21,7 +21,7 @@ interface GroupVerify<in S, in T : Any> {
 
 interface GroupClause<in S : ContractState, in T : Any> : Clause, GroupVerify<S, T>
 
-abstract class GroupClauseVerifier<S : ContractState, T : Any> : SingleClause {
+abstract class GroupClauseVerifier<S : ContractState, T : Any> : SingleClause() {
     abstract val clauses: List<GroupClause<S, T>>
     override val requiredCommands: Set<Class<out CommandData>>
         get() = emptySet()
diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/clauses/InterceptorClause.kt b/core/src/main/kotlin/com/r3corda/core/contracts/clauses/InterceptorClause.kt
index 9f9f4d3625..e1a64d58d6 100644
--- a/core/src/main/kotlin/com/r3corda/core/contracts/clauses/InterceptorClause.kt
+++ b/core/src/main/kotlin/com/r3corda/core/contracts/clauses/InterceptorClause.kt
@@ -9,10 +9,10 @@ import java.util.*
  * A clause which intercepts calls to a wrapped clause, and passes them through verification
  * only from a pre-clause. This is similar to an inceptor in aspect orientated programming.
  */
-data class InterceptorClause(
+class InterceptorClause(
         val preclause: SingleVerify,
         val clause: SingleClause
-) : SingleClause {
+) : SingleClause() {
     override val ifNotMatched: MatchBehaviour
         get() = clause.ifNotMatched
     override val ifMatched: MatchBehaviour
@@ -25,4 +25,6 @@ data class InterceptorClause(
         consumed.addAll(clause.verify(tx, commands))
         return consumed
     }
+
+    override fun toString(): String = "Interceptor clause [${clause}]"
 }
\ No newline at end of file
diff --git a/core/src/test/kotlin/com/r3corda/core/contracts/clauses/VerifyClausesTests.kt b/core/src/test/kotlin/com/r3corda/core/contracts/clauses/VerifyClausesTests.kt
index b97d943745..271a1588f2 100644
--- a/core/src/test/kotlin/com/r3corda/core/contracts/clauses/VerifyClausesTests.kt
+++ b/core/src/test/kotlin/com/r3corda/core/contracts/clauses/VerifyClausesTests.kt
@@ -19,11 +19,7 @@ class VerifyClausesTests {
     /** Very simple check that the function doesn't error when given any clause */
     @Test
     fun minimal() {
-        val clause = object : SingleClause {
-            override val requiredCommands: Set<Class<out CommandData>>
-                get() = emptySet()
-            override val ifMatched: MatchBehaviour
-                get() = MatchBehaviour.CONTINUE
+        val clause = object : SingleClause() {
             override val ifNotMatched: MatchBehaviour
                 get() = MatchBehaviour.CONTINUE
 
@@ -36,14 +32,7 @@ class VerifyClausesTests {
     /** Check that when there are no required commands, a clause always matches */
     @Test
     fun emptyAlwaysMatches() {
-        val clause = object : SingleClause {
-            override val requiredCommands: Set<Class<out CommandData>>
-                get() = emptySet()
-            override val ifMatched: MatchBehaviour
-                get() = MatchBehaviour.CONTINUE
-            override val ifNotMatched: MatchBehaviour
-                get() = MatchBehaviour.ERROR
-
+        val clause = object : SingleClause() {
             override fun verify(tx: TransactionForContract, commands: Collection<AuthenticatedObject<CommandData>>): Set<CommandData> = emptySet()
         }
         val tx = TransactionForContract(emptyList(), emptyList(), emptyList(), emptyList(), SecureHash.randomSHA256())
@@ -53,9 +42,7 @@ class VerifyClausesTests {
 
     @Test
     fun errorSuperfluousCommands() {
-        val clause = object : SingleClause {
-            override val requiredCommands: Set<Class<out CommandData>>
-                get() = emptySet()
+        val clause = object : SingleClause() {
             override val ifMatched: MatchBehaviour
                 get() = MatchBehaviour.ERROR
             override val ifNotMatched: MatchBehaviour
@@ -73,7 +60,7 @@ class VerifyClausesTests {
     /** Check triggering of error if matched */
     @Test
     fun errorMatched() {
-        val clause = object : SingleClause {
+        val clause = object : SingleClause() {
             override val requiredCommands: Set<Class<out CommandData>>
                 get() = setOf(DummyContract.Commands.Create::class.java)
             override val ifMatched: MatchBehaviour
@@ -98,13 +85,9 @@ class VerifyClausesTests {
     /** Check triggering of error if unmatched */
     @Test
     fun errorUnmatched() {
-        val clause = object : SingleClause {
+        val clause = object : SingleClause() {
             override val requiredCommands: Set<Class<out CommandData>>
                 get() = setOf(DummyContract.Commands.Create::class.java)
-            override val ifMatched: MatchBehaviour
-                get() = MatchBehaviour.CONTINUE
-            override val ifNotMatched: MatchBehaviour
-                get() = MatchBehaviour.ERROR
 
             override fun verify(tx: TransactionForContract, commands: Collection<AuthenticatedObject<CommandData>>): Set<CommandData> = emptySet()
         }
diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst
index 778691f8bc..04ea2ef75e 100644
--- a/docs/source/release-notes.rst
+++ b/docs/source/release-notes.rst
@@ -54,6 +54,7 @@ API changes:
 * The ``arg`` method in the test DSL is now called ``command`` to be consistent with the rest of the data model.
 * The messaging APIs have changed somewhat to now use a new ``TopicSession`` object. These APIs will continue to change
   in the upcoming releases.
+* Clauses now have default values provided for ``ifMatched``, ``ifNotMatched`` and ``requiredCommands``.
 
 New documentation:
 
diff --git a/docs/source/tutorial-contract-clauses.rst b/docs/source/tutorial-contract-clauses.rst
index 47948b0aef..eb1ee343c0 100644
--- a/docs/source/tutorial-contract-clauses.rst
+++ b/docs/source/tutorial-contract-clauses.rst
@@ -16,13 +16,13 @@ generally the same for all fungible contracts, so a single issuance clause can b
 error, and improves consistency of behaviour.
 
 Clauses can be composed of subclauses, either to combine clauses in different ways, or to apply specialised clauses.
-In the case of commercial paper, we have a "Grouping" outermost clause, which will contain the "Issue", "Move" and
-"Redeem" clauses. The result is a contract that looks something like this:
+In the case of commercial paper, we have a ``Group`` outermost clause, which will contain the ``Issue``, ``Move`` and
+``Redeem`` clauses. The result is a contract that looks something like this:
 
     1. Group input and output states together, and then apply the following clauses on each group:
-        a. If an Issue command is present, run appropriate tests and end processing this group.
-        b. If a Move command is present, run appropriate tests and end processing this group.
-        c. If a Redeem command is present, run appropriate tests and end processing this group.
+        a. If an ``Issue`` command is present, run appropriate tests and end processing this group.
+        b. If a ``Move`` command is present, run appropriate tests and end processing this group.
+        c. If a ``Redeem`` command is present, run appropriate tests and end processing this group.
 
 Commercial paper class
 ----------------------
@@ -71,9 +71,9 @@ Clauses
 
 We'll tackle the inner clauses that contain the bulk of the verification logic, first, and the clause which handles
 grouping of input/output states later. The inner clauses need to implement the ``GroupClause`` interface, which defines
-the verify() function, and properties for key information on how the clause is processed. These properties specify the
-command(s) which must be present in order for the clause to be matched, and what to do after processing the clause
-depending on whether it was matched or not.
+the verify() function, and properties (``ifMatched``, ``ifNotMatched`` and ``requiredCommands``) defining how the clause
+is processed. These properties specify the command(s) which must be present in order for the clause to be matched,
+and what to do after processing the clause depending on whether it was matched or not.
 
 The ``verify()`` functions defined in the ``SingleClause`` and ``GroupClause`` interfaces is similar to the conventional
 ``Contract`` verification function, although it adds new parameters and returns the set of commands which it has processed.
@@ -157,7 +157,9 @@ The post-processing ``MatchBehaviour`` options are:
     * ERROR
 
 In this case we process commands against each group, until the first matching clause is found, so we ``END`` on a match
-and ``CONTINUE`` otherwise. ``ERROR`` can be used as a part of a clause which must always/never be matched.
+and ``CONTINUE`` otherwise. ``ERROR`` can be used as a part of a clause which must always/never be matched.  By default
+clauses are always matched (``requiredCommands`` is an empty set), execution continues after a clause is matched, and an
+error is raised if a clause is not matched.
 
 Group Clause
 ------------