diff --git a/contracts/src/main/kotlin/contracts/IRS.kt b/contracts/src/main/kotlin/contracts/IRS.kt
index 0666415603..008b382fe5 100644
--- a/contracts/src/main/kotlin/contracts/IRS.kt
+++ b/contracts/src/main/kotlin/contracts/IRS.kt
@@ -19,15 +19,24 @@ open class UnknownType() {
         return (other is UnknownType)
     }
 
-    override fun hashCode(): Int {
-        return 1
-    }
+    override fun hashCode() = 1
 }
 
 /**
  * Event superclass - everything happens on a date.
  */
-open class Event(val date: LocalDate)
+open class Event(val date: LocalDate) {
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is Event) return false
+
+        if (date != other.date) return false
+
+        return true
+    }
+
+    override fun hashCode() = Objects.hash(date)
+}
 
 /**
  * Top level PaymentEvent class - represents an obligation to pay an amount on a given date, which may be either in the past or the future.
@@ -58,14 +67,30 @@ abstract class RatePaymentEvent(date: LocalDate,
 
     abstract val flow: Amount
 
-    val days: Int get() =
-        calculateDaysBetween(accrualStartDate, accrualEndDate, dayCountBasisYear, dayCountBasisDay)
+    val days: Int get() = calculateDaysBetween(accrualStartDate, accrualEndDate, dayCountBasisYear, dayCountBasisDay)
 
-    val dayCountFactor: BigDecimal get() =
-        // TODO : Fix below (use daycount convention for division)
-        (BigDecimal(days).divide(BigDecimal(360.0), 8, RoundingMode.HALF_UP)).setScale(4, RoundingMode.HALF_UP)
+    // TODO : Fix below (use daycount convention for division, not hardcoded 360 etc)
+    val dayCountFactor: BigDecimal get() = (BigDecimal(days).divide(BigDecimal(360.0), 8, RoundingMode.HALF_UP)).setScale(4, RoundingMode.HALF_UP)
 
-    open fun asCSV(): String = "$accrualStartDate,$accrualEndDate,$dayCountFactor,$days,$date,${notional.currency},${notional},$rate,$flow"
+    open fun asCSV() = "$accrualStartDate,$accrualEndDate,$dayCountFactor,$days,$date,${notional.currency},${notional},$rate,$flow"
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is RatePaymentEvent) return false
+
+        if (accrualStartDate != other.accrualStartDate) return false
+        if (accrualEndDate != other.accrualEndDate) return false
+        if (dayCountBasisDay != other.dayCountBasisDay) return false
+        if (dayCountBasisYear != other.dayCountBasisYear) return false
+        if (notional != other.notional) return false
+        if (rate != other.rate) return false
+        // if (flow != other.flow) return false // Flow is derived
+
+        return super.equals(other)
+    }
+
+    override fun hashCode() = super.hashCode() + 31 * Objects.hash(accrualStartDate, accrualEndDate, dayCountBasisDay,
+            dayCountBasisYear, notional, rate)
 }
 
 /**
@@ -114,9 +139,7 @@ class FloatingRatePaymentEvent(date: LocalDate,
         return Amount(dayCountFactor.times(BigDecimal(notional.pennies)).times(v).toLong(), notional.currency)
     }
 
-    override fun toString(): String {
-        return "FloatingPaymentEvent $accrualStartDate -> $accrualEndDate : $dayCountFactor : $days : $date : $notional : $rate (fix on $fixingDate): $flow"
-    }
+    override fun toString(): String = "FloatingPaymentEvent $accrualStartDate -> $accrualEndDate : $dayCountFactor : $days : $date : $notional : $rate (fix on $fixingDate): $flow"
 
     override fun asCSV(): String = "$accrualStartDate,$accrualEndDate,$dayCountFactor,$days,$date,${notional.currency},${notional},$fixingDate,$rate,$flow"
 
@@ -126,6 +149,26 @@ class FloatingRatePaymentEvent(date: LocalDate,
     fun withNewRate(newRate: Rate): FloatingRatePaymentEvent =
             FloatingRatePaymentEvent(date, accrualStartDate, accrualEndDate, dayCountBasisDay,
                     dayCountBasisYear, fixingDate, notional, newRate)
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other?.javaClass != javaClass) return false
+        other as FloatingRatePaymentEvent
+        if (fixingDate != other.fixingDate) return false
+        return super.equals(other)
+    }
+
+    override fun hashCode() = super.hashCode() + 31 * Objects.hash(fixingDate)
+
+    // Can't autogenerate as not a data class :-(
+    fun copy(date: LocalDate = this.date,
+             accrualStartDate: LocalDate = this.accrualStartDate,
+             accrualEndDate: LocalDate = this.accrualEndDate,
+             dayCountBasisDay: DayCountBasisDay = this.dayCountBasisDay,
+             dayCountBasisYear: DayCountBasisYear = this.dayCountBasisYear,
+             fixingDate: LocalDate = this.fixingDate,
+             notional: Amount = this.notional,
+             rate: Rate = this.rate) = FloatingRatePaymentEvent(date, accrualStartDate, accrualEndDate, dayCountBasisDay, dayCountBasisYear, fixingDate, notional, rate)
 }
 
 
@@ -191,18 +234,13 @@ class InterestRateSwap() : Contract {
         /**
          * Returns a copy after modifying (applying) the fixing for that date.
          */
-        fun applyFixing(date: LocalDate, newRate: Rate): Calculation {
+        fun applyFixing(date: LocalDate, newRate: FixedRate): Calculation {
             val paymentEvent = getFixing(date)
             val newFloatingLPS = floatingLegPaymentSchedule + (paymentEvent.date to paymentEvent.withNewRate(newRate))
             return Calculation(expression = expression,
                     floatingLegPaymentSchedule = newFloatingLPS,
                     fixedLegPaymentSchedule = fixedLegPaymentSchedule)
         }
-
-        fun exportSchedule() {
-
-        }
-
     }
 
     abstract class CommonLeg(
@@ -212,13 +250,13 @@ class InterestRateSwap() : Contract {
             val effectiveDateAdjustment: DateRollConvention?,
             val terminationDate: LocalDate,
             val terminationDateAdjustment: DateRollConvention?,
-            var dayCountBasisDay: DayCountBasisDay,
-            var dayCountBasisYear: DayCountBasisYear,
-            var dayInMonth: Int,
-            var paymentRule: PaymentRule,
-            var paymentDelay: Int,
-            var paymentCalendar: BusinessCalendar,
-            var interestPeriodAdjustment: AccrualAdjustment
+            val dayCountBasisDay: DayCountBasisDay,
+            val dayCountBasisYear: DayCountBasisYear,
+            val dayInMonth: Int,
+            val paymentRule: PaymentRule,
+            val paymentDelay: Int,
+            val paymentCalendar: BusinessCalendar,
+            val interestPeriodAdjustment: AccrualAdjustment
     ) {
         override fun toString(): String {
             return "Notional=$notional,PaymentFrequency=$paymentFrequency,EffectiveDate=$effectiveDate,EffectiveDateAdjustment:$effectiveDateAdjustment,TerminatationDate=$terminationDate," +
@@ -249,24 +287,9 @@ class InterestRateSwap() : Contract {
             return true
         }
 
-        override fun hashCode(): Int {
-            var result = notional.hashCode()
-            result += 31 * result + paymentFrequency.hashCode()
-            result += 31 * result + effectiveDate.hashCode()
-            result += 31 * result + (effectiveDateAdjustment?.hashCode() ?: 0)
-            result += 31 * result + terminationDate.hashCode()
-            result += 31 * result + (terminationDateAdjustment?.hashCode() ?: 0)
-            result += 31 * result + dayCountBasisDay.hashCode()
-            result += 31 * result + dayCountBasisYear.hashCode()
-            result += 31 * result + dayInMonth
-            result += 31 * result + paymentRule.hashCode()
-            result += 31 * result + paymentDelay
-            result += 31 * result + paymentCalendar.hashCode()
-            result += 31 * result + interestPeriodAdjustment.hashCode()
-            return result
-        }
-
-
+        override fun hashCode() = super.hashCode() + 31 * Objects.hash(notional, paymentFrequency, effectiveDate,
+                effectiveDateAdjustment, terminationDate, effectiveDateAdjustment, terminationDate, terminationDateAdjustment,
+                dayCountBasisDay, dayCountBasisYear, dayInMonth, paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment)
     }
 
     open class FixedLeg(
@@ -306,13 +329,27 @@ class InterestRateSwap() : Contract {
             return true
         }
 
-        override fun hashCode(): Int {
-            var result = super.hashCode()
-            result += 31 * result + fixedRatePayer.hashCode()
-            result += 31 * result + fixedRate.hashCode()
-            result += 31 * result + rollConvention.hashCode()
-            return result
-        }
+        override fun hashCode() = super.hashCode() + 31 * Objects.hash(fixedRatePayer, fixedRate, rollConvention)
+
+        // Can't autogenerate as not a data class :-(
+        fun copy(fixedRatePayer: Party = this.fixedRatePayer,
+                 notional: Amount = this.notional,
+                 paymentFrequency: Frequency = this.paymentFrequency,
+                 effectiveDate: LocalDate = this.effectiveDate,
+                 effectiveDateAdjustment: DateRollConvention? = this.effectiveDateAdjustment,
+                 terminationDate: LocalDate = this.terminationDate,
+                 terminationDateAdjustment: DateRollConvention? = this.terminationDateAdjustment,
+                 dayCountBasisDay: DayCountBasisDay = this.dayCountBasisDay,
+                 dayCountBasisYear: DayCountBasisYear = this.dayCountBasisYear,
+                 dayInMonth: Int = this.dayInMonth,
+                 paymentRule: PaymentRule = this.paymentRule,
+                 paymentDelay: Int = this.paymentDelay,
+                 paymentCalendar: BusinessCalendar = this.paymentCalendar,
+                 interestPeriodAdjustment: AccrualAdjustment = this.interestPeriodAdjustment,
+                 fixedRate: FixedRate = this.fixedRate) = FixedLeg(
+                fixedRatePayer, notional, paymentFrequency, effectiveDate, effectiveDateAdjustment, terminationDate,
+                terminationDateAdjustment, dayCountBasisDay, dayCountBasisYear, dayInMonth, paymentRule, paymentDelay,
+                paymentCalendar, interestPeriodAdjustment, fixedRate, rollConvention)
 
     }
 
@@ -370,62 +407,168 @@ class InterestRateSwap() : Contract {
             return true
         }
 
-        override fun hashCode(): Int {
-            var result = super.hashCode()
-            result += 31 * result + floatingRatePayer.hashCode()
-            result += 31 * result + rollConvention.hashCode()
-            result += 31 * result + fixingRollConvention.hashCode()
-            result += 31 * result + resetDayInMonth
-            result += 31 * result + fixingPeriod.hashCode()
-            result += 31 * result + resetRule.hashCode()
-            result += 31 * result + fixingsPerPayment.hashCode()
-            result += 31 * result + fixingCalendar.hashCode()
-            result += 31 * result + index.hashCode()
-            result += 31 * result + indexSource.hashCode()
-            result += 31 * result + indexTenor.hashCode()
-            return result
+        override fun hashCode() = super.hashCode() + 31 * Objects.hash(floatingRatePayer, rollConvention,
+                fixingRollConvention, resetDayInMonth, fixingPeriod, resetRule, fixingsPerPayment, fixingCalendar,
+                index, indexSource, indexTenor)
+
+
+        fun copy(floatingRatePayer: Party = this.floatingRatePayer,
+                 notional: Amount = this.notional,
+                 paymentFrequency: Frequency = this.paymentFrequency,
+                 effectiveDate: LocalDate = this.effectiveDate,
+                 effectiveDateAdjustment: DateRollConvention? = this.effectiveDateAdjustment,
+                 terminationDate: LocalDate = this.terminationDate,
+                 terminationDateAdjustment: DateRollConvention? = this.terminationDateAdjustment,
+                 dayCountBasisDay: DayCountBasisDay = this.dayCountBasisDay,
+                 dayCountBasisYear: DayCountBasisYear = this.dayCountBasisYear,
+                 dayInMonth: Int = this.dayInMonth,
+                 paymentRule: PaymentRule = this.paymentRule,
+                 paymentDelay: Int = this.paymentDelay,
+                 paymentCalendar: BusinessCalendar = this.paymentCalendar,
+                 interestPeriodAdjustment: AccrualAdjustment = this.interestPeriodAdjustment,
+                 rollConvention: DateRollConvention = this.rollConvention,
+                 fixingRollConvention: DateRollConvention = this.fixingRollConvention,
+                 resetDayInMonth: Int = this.resetDayInMonth,
+                 fixingPeriod: DateOffset = this.fixingPeriod,
+                 resetRule: PaymentRule = this.resetRule,
+                 fixingsPerPayment: Frequency = this.fixingsPerPayment,
+                 fixingCalendar: BusinessCalendar = this.fixingCalendar,
+                 index: String = this.index,
+                 indexSource: String = this.indexSource,
+                 indexTenor: Tenor = this.indexTenor
+        ) = FloatingLeg(floatingRatePayer, notional, paymentFrequency, effectiveDate, effectiveDateAdjustment,
+                terminationDate, terminationDateAdjustment, dayCountBasisDay, dayCountBasisYear, dayInMonth,
+                paymentRule, paymentDelay, paymentCalendar, interestPeriodAdjustment, rollConvention,
+                fixingRollConvention, resetDayInMonth, fixingPeriod, resetRule, fixingsPerPayment,
+                fixingCalendar, index, indexSource, indexTenor)
+    }
+
+    // These functions may make more sense to use for basket types, but for now let's leave them here
+    fun checkLegDates(legs: Array<CommonLeg>) {
+        requireThat {
+            "Effective date is before termination date" by legs.all { it.effectiveDate < it.terminationDate }
+            "Effective dates are in alignment" by legs.all { it.effectiveDate == legs[0].effectiveDate }
+            "Termination dates are in alignment" by legs.all { it.terminationDate == legs[0].terminationDate }
+        }
+    }
+
+    fun checkLegAmounts(legs: Array<CommonLeg>) {
+        requireThat {
+            "The notional is non zero" by legs.any { it.notional.pennies > (0).toLong() }
+            "The notional for all legs must be the same" by legs.all { it.notional == legs[0].notional }
+        }
+        for (leg: CommonLeg in legs) {
+            if (leg is FixedLeg) {
+                requireThat {
+                    // TODO: Confirm: would someone really enter a swap with a negative fixed rate?
+                    "Fixed leg rate must be positive" by leg.fixedRate.isPositive()
+                }
+            }
         }
 
     }
 
+    // TODO: After business rules discussion, add further checks to the schedules and rates
+    fun checkSchedules(@Suppress("UNUSED_PARAMETER") legs: Array<CommonLeg>): Boolean = true
+
+    fun checkRates(@Suppress("UNUSED_PARAMETER") legs: Array<CommonLeg>): Boolean = true
+
     /**
-     * verify() with a few examples of what needs to be checked. TODO: Lots more to add.
+     * Compares two schedules of Floating Leg Payments, returns the difference (i.e. omissions in either leg or changes to the values).
+     */
+    fun getFloatingLegPaymentsDifferences(payments1: Map<LocalDate, Event>, payments2: Map<LocalDate, Event>): List<Pair<LocalDate, Pair<FloatingRatePaymentEvent, FloatingRatePaymentEvent>>> {
+        val diff1 = payments1.filter { payments1[it.key] != payments2[it.key] }
+        val diff2 = payments2.filter { payments1[it.key] != payments2[it.key] }
+        val ret = (diff1.keys + diff2.keys).map { it to Pair(diff1.get(it) as FloatingRatePaymentEvent, diff2.get(it) as FloatingRatePaymentEvent) }
+        return ret
+    }
+
+    /**
+     * verify() with some examples of what needs to be checked.
      */
     override fun verify(tx: TransactionForVerification) {
+
+        // Group by Trade ID for in / out states
+        val groups = tx.groupStates() { state: InterestRateSwap.State -> state.common.tradeID }
+
         val command = tx.commands.requireSingleCommand<InterestRateSwap.Commands>()
         val time = tx.commands.getTimestampByName("Mock Company 0", "Timestamping Service", "Bank A")?.midpoint
         if (time == null) throw IllegalArgumentException("must be timestamped")
 
-        val irs = tx.outStates.filterIsInstance<InterestRateSwap.State>().single()
-        when (command.value) {
-            is Commands.Agree -> {
-                requireThat {
-                    "There are no in states for an agreement" by tx.inStates.isEmpty()
-                    "The fixed rate is non zero" by (irs.fixedLeg.fixedRate != FixedRate(PercentageRatioUnit("0.0")))
-                    "There are events in the fix schedule" by (irs.calculation.fixedLegPaymentSchedule.size > 0)
-                    "There are events in the float schedule" by (irs.calculation.floatingLegPaymentSchedule.size > 0)
-                    // "There are fixes in the schedule" by (irs.calculation.floatingLegPaymentSchedule!!.size > 0)
-                    // TODO: shortlist of other tests
-                }
-            }
-            is Commands.Fix -> {
-                requireThat {
-                    // TODO: see previous block
-                    // "There is a fixing supplied" by false // TODO
-                    //  "The fixing has been signed by an appropriate oracle" by false // TODO
-                    // "The fixing has arrived at the right time" by false
-                    // "The net payment has been calculated" by false // TODO : Not sure if this is the right place
+        for ((inputs, outputs, key) in groups) {
+            when (command.value) {
+                is Commands.Agree -> {
+                    val irs = outputs.filterIsInstance<InterestRateSwap.State>().single()
+                    requireThat {
+                        "There are no in states for an agreement" by inputs.isEmpty()
+                        "There are events in the fix schedule" by (irs.calculation.fixedLegPaymentSchedule.size > 0)
+                        "There are events in the float schedule" by (irs.calculation.floatingLegPaymentSchedule.size > 0)
+                        "All notionals must be non zero" by ( irs.fixedLeg.notional.pennies > 0 && irs.floatingLeg.notional.pennies > 0)
+                        "The fixed leg rate must be positive" by ( irs.fixedLeg.fixedRate.isPositive() )
+                        "The currency of the notionals must be the same" by (irs.fixedLeg.notional.currency == irs.floatingLeg.notional.currency)
+                        "All leg notionals must be the same" by (irs.fixedLeg.notional == irs.floatingLeg.notional)
 
+                        "The effective date is before the termination date for the fixed leg" by (irs.fixedLeg.effectiveDate < irs.fixedLeg.terminationDate)
+                        "The effective date is before the termination date for the floating leg" by (irs.floatingLeg.effectiveDate < irs.floatingLeg.terminationDate)
+                        "The effective dates are aligned" by (irs.floatingLeg.effectiveDate == irs.fixedLeg.effectiveDate)
+                        "The termination dates are aligned" by (irs.floatingLeg.terminationDate == irs.fixedLeg.terminationDate)
+                        "The rates are valid" by checkRates(arrayOf(irs.fixedLeg, irs.floatingLeg))
+                        "The schedules are valid" by checkSchedules(arrayOf(irs.fixedLeg, irs.floatingLeg))
+
+
+                        // TODO: further tests
+                    }
+                    checkLegAmounts(arrayOf(irs.fixedLeg, irs.floatingLeg))
+                    checkLegDates(arrayOf(irs.fixedLeg, irs.floatingLeg))
                 }
-            }
-            is Commands.Pay -> {
-                requireThat {
-                    // TODO: see previous block
-                    //"A counterparty must be making a payment" by false // TODO
-                    // "The right counterparty must be receiving the payment" by false // TODO
+                is Commands.Fix -> {
+                    val irs = outputs.filterIsInstance<InterestRateSwap.State>().single()
+                    val prevIrs = inputs.filterIsInstance<InterestRateSwap.State>().single()
+                    val paymentDifferences = getFloatingLegPaymentsDifferences(prevIrs.calculation.floatingLegPaymentSchedule, irs.calculation.floatingLegPaymentSchedule)
+
+                    // Having both of these tests are "redundant" as far as verify() goes, however, by performing both
+                    // we can relay more information back to the user in the case of failure.
+                    requireThat {
+                        "There is at least one difference in the IRS floating leg payment schedules" by !paymentDifferences.isEmpty()
+                        "There is only one change in the IRS floating leg payment schedule" by (paymentDifferences.size == 1)
+                    }
+
+                    val changedRates = paymentDifferences.single().second // Ignore the date of the changed rate (we checked that earlier).
+                    val (oldFloatingRatePaymentEvent, newFixedRatePaymentEvent) = changedRates
+                    val fixCommand = tx.commands.requireSingleCommand<Fix>()
+                    val fixValue = fixCommand.value
+                    // Need to check that everything is the same apart from the new fixed rate entry.
+                    requireThat {
+                        "The fixed leg parties are constant" by ( irs.fixedLeg.fixedRatePayer == prevIrs.fixedLeg.fixedRatePayer) // Although superseded by the below test, this is included for a regression issue
+                        "The fixed leg is constant" by (irs.fixedLeg == prevIrs.fixedLeg)
+                        "The floating leg is constant" by (irs.floatingLeg == prevIrs.floatingLeg)
+                        "The common values are constant" by (irs.common == prevIrs.common)
+                        "The fixed leg payment schedule is constant" by (irs.calculation.fixedLegPaymentSchedule == prevIrs.calculation.fixedLegPaymentSchedule)
+                        "The expression is unchanged" by (irs.calculation.expression == prevIrs.calculation.expression)
+                        "There is only one changed payment in the floating leg" by (paymentDifferences.size == 1)
+                        "There changed payment is a floating payment" by (oldFloatingRatePaymentEvent.rate is ReferenceRate)
+                        "The new payment is a fixed payment" by (newFixedRatePaymentEvent.rate is FixedRate)
+                        "The changed payments dates are aligned" by ( oldFloatingRatePaymentEvent.date == newFixedRatePaymentEvent.date)
+                        "The new payment has the correct rate" by (newFixedRatePaymentEvent.rate.ratioUnit!!.value == fixValue.value)
+                        "The fixing is for the next required date" by (prevIrs.calculation.nextFixingDate() == fixValue.of.forDay)
+                        "The fix payment has the same currency as the notional" by (newFixedRatePaymentEvent.flow.currency == irs.floatingLeg.notional.currency)
+                        // "The fixing is not in the future " by (fixCommand) // The oracle should not have signed this .
+                    }
                 }
+                is Commands.Pay -> {
+                    requireThat {
+                        "Payments not supported / verifiable yet" by false
+                    }
+                }
+                is Commands.Mature -> {
+                    val irs = inputs.filterIsInstance<InterestRateSwap.State>().single()
+                    requireThat {
+                        "No more fixings to be applied" by (irs.calculation.nextFixingDate() == null)
+                    }
+                }
+
+                else -> throw IllegalArgumentException("Unrecognised verifiable command: ${command.value}")
             }
-            else -> throw IllegalArgumentException("Unrecognised verifiable command: ${command.value}")
         }
     }
 
@@ -510,6 +653,7 @@ class InterestRateSwap() : Contract {
          * Just makes printing it out a bit better for those who don't have 80000 column wide monitors.
          */
         fun prettyPrint(): String = toString().replace(",", "\n")
+
     }
 
     /**
@@ -580,7 +724,7 @@ class InterestRateSwap() : Contract {
     // TODO: Replace with rates oracle
     fun generateFix(tx: TransactionBuilder, irs: StateAndRef<State>, fixing: Pair<LocalDate, Rate>) {
         tx.addInputState(irs.ref)
-        tx.addOutputState(irs.state.copy(calculation = irs.state.calculation.applyFixing(fixing.first, fixing.second)))
+        tx.addOutputState(irs.state.copy(calculation = irs.state.calculation.applyFixing(fixing.first, FixedRate(fixing.second))))
         tx.addCommand(Commands.Fix(), listOf(irs.state.floatingLeg.floatingRatePayer.owningKey, irs.state.fixedLeg.fixedRatePayer.owningKey))
     }
 }
diff --git a/contracts/src/main/kotlin/contracts/IRSUtils.kt b/contracts/src/main/kotlin/contracts/IRSUtils.kt
index da60600fe6..936b73584a 100644
--- a/contracts/src/main/kotlin/contracts/IRSUtils.kt
+++ b/contracts/src/main/kotlin/contracts/IRSUtils.kt
@@ -24,17 +24,14 @@ open class RatioUnit(value: BigDecimal) { // TODO: Discuss this type
         return true
     }
 
-    override fun hashCode(): Int {
-        return value.hashCode()
-    }
-
+    override fun hashCode() = value.hashCode()
 }
 
 /**
  * A class to reprecent a percentage in an unambiguous way.
  */
 open class PercentageRatioUnit(percentageAsString: String) : RatioUnit(BigDecimal(percentageAsString).divide(BigDecimal("100"))) {
-    override fun toString(): String = value.times(BigDecimal(100)).toString() + "%"
+    override fun toString() = value.times(BigDecimal(100)).toString() + "%"
 }
 
 /**
@@ -111,16 +108,23 @@ open class Rate(val ratioUnit: RatioUnit? = null) {
      * that have not yet happened.  Yet-to-be fixed floating rates need to be equal such that schedules can be tested
      * for equality.
      */
-    override fun hashCode(): Int {
-        return ratioUnit?.hashCode() ?: 0
-    }
+    override fun hashCode() = ratioUnit?.hashCode() ?: 0
 }
 
 /**
  * A very basic subclass to represent a fixed rate.
  */
 class FixedRate(ratioUnit: RatioUnit) : Rate(ratioUnit) {
+
+    constructor(otherRate: Rate) : this(ratioUnit = otherRate.ratioUnit!!)
+
     override fun toString(): String = "$ratioUnit"
+
+    fun isPositive(): Boolean = ratioUnit!!.value > BigDecimal("0.0")
+
+    override fun equals(other: Any?) = other?.javaClass == javaClass && super.equals(other)
+
+    override fun hashCode() = super.hashCode()
 }
 
 /**
diff --git a/scripts/example-irs-trade.json b/scripts/example-irs-trade.json
index fc8d17eef3..7338404bdc 100644
--- a/scripts/example-irs-trade.json
+++ b/scripts/example-irs-trade.json
@@ -6,9 +6,9 @@
       "currency": "USD"
     },
     "paymentFrequency": "SemiAnnual",
-    "effectiveDate": "2016-03-16",
+    "effectiveDate": "2016-03-11",
     "effectiveDateAdjustment": null,
-    "terminationDate": "2026-03-16",
+    "terminationDate": "2026-03-11",
     "terminationDateAdjustment": null,
     "fixedRate": {
       "ratioUnit": {
@@ -31,9 +31,9 @@
       "currency": "USD"
     },
     "paymentFrequency": "Quarterly",
-    "effectiveDate": "2016-03-12",
+    "effectiveDate": "2016-03-11",
     "effectiveDateAdjustment": null,
-    "terminationDate": "2026-03-12",
+    "terminationDate": "2026-03-11",
     "terminationDateAdjustment": null,
     "dayCountBasisDay": "D30",
     "dayCountBasisYear": "Y360",
diff --git a/scripts/example.rates.txt b/scripts/example.rates.txt
index cb49751d27..2b9893f806 100644
--- a/scripts/example.rates.txt
+++ b/scripts/example.rates.txt
@@ -5,7 +5,8 @@ ICE LIBOR 2016-03-16 2M = 0.655
 EURIBOR 2016-03-15 1M = 0.123
 EURIBOR 2016-03-15 2M = 0.111
 
-ICE LIBOR 2016-03-06 3M = 0.0063515
+# Previous fixings
+ICE LIBOR 2016-03-07 3M = 0.0063516
 ICE LIBOR 2016-03-07 3M = 0.0063516
 ICE LIBOR 2016-03-08 3M = 0.0063517
 ICE LIBOR 2016-03-09 3M = 0.0063518
diff --git a/src/main/kotlin/core/node/subsystems/Services.kt b/src/main/kotlin/core/node/subsystems/Services.kt
index 4d65544351..c969193418 100644
--- a/src/main/kotlin/core/node/subsystems/Services.kt
+++ b/src/main/kotlin/core/node/subsystems/Services.kt
@@ -113,6 +113,8 @@ interface KeyManagementService {
 
     fun toPrivate(publicKey: PublicKey) = keys[publicKey] ?: throw IllegalStateException("No private key known for requested public key")
 
+    fun toKeyPair(publicKey: PublicKey) = KeyPair(publicKey, toPrivate(publicKey))
+
     /** Generates a new random key and adds it to the exposed map. */
     fun freshKey(): KeyPair
 }
diff --git a/src/main/kotlin/demos/protocols/UpdateBusinessDayProtocol.kt b/src/main/kotlin/demos/protocols/UpdateBusinessDayProtocol.kt
index fa43e6f642..be8ef4fdb4 100644
--- a/src/main/kotlin/demos/protocols/UpdateBusinessDayProtocol.kt
+++ b/src/main/kotlin/demos/protocols/UpdateBusinessDayProtocol.kt
@@ -15,6 +15,7 @@ import core.utilities.ANSIProgressRenderer
 import core.utilities.ProgressTracker
 import demos.DemoClock
 import protocols.TwoPartyDealProtocol
+import java.security.KeyPair
 import java.time.LocalDate
 
 /**
@@ -98,7 +99,13 @@ object UpdateBusinessDayProtocol {
             progressTracker.childrenFor[FIXING] = TwoPartyDealProtocol.Primary.tracker()
             progressTracker.currentStep = FIXING
 
-            val participant = TwoPartyDealProtocol.Floater(party.address, sessionID, serviceHub.networkMapCache.timestampingNodes[0], dealStateAndRef, serviceHub.keyManagementService.freshKey(), sessionID, progressTracker.childrenFor[FIXING]!!)
+            val myName = serviceHub.storageService.myLegalIdentity.name
+            val deal: InterestRateSwap.State = dealStateAndRef.state
+            val myOldParty = deal.parties.single { it.name == myName }
+            val keyPair = serviceHub.keyManagementService.toKeyPair(myOldParty.owningKey)
+            val participant = TwoPartyDealProtocol.Floater(party.address, sessionID, serviceHub.networkMapCache.timestampingNodes[0], dealStateAndRef,
+                    keyPair,
+                    sessionID, progressTracker.childrenFor[FIXING]!!)
             val result = subProtocol(participant)
             return result.tx.outRef(0)
         }
diff --git a/src/main/kotlin/protocols/TwoPartyDealProtocol.kt b/src/main/kotlin/protocols/TwoPartyDealProtocol.kt
index c0c6f08f82..7880a28113 100644
--- a/src/main/kotlin/protocols/TwoPartyDealProtocol.kt
+++ b/src/main/kotlin/protocols/TwoPartyDealProtocol.kt
@@ -367,10 +367,9 @@ object TwoPartyDealProtocol {
             val deal: T = dealToFix.state
             val myOldParty = deal.parties.single { it.name == myName }
             val theirOldParty = deal.parties.single { it.name != myName }
-            val myNewKey = serviceHub.keyManagementService.freshKey().public
 
             @Suppress("UNCHECKED_CAST")
-            val newDeal = deal.withPublicKey(myOldParty, myNewKey).withPublicKey(theirOldParty, handshake.publicKey) as T
+            val newDeal = deal
             val oldRef = dealToFix.ref
 
             val ptx = TransactionBuilder()
@@ -386,7 +385,7 @@ object TwoPartyDealProtocol {
             }
             subProtocol(addFixing)
 
-            return Pair(ptx, arrayListOf(myNewKey))
+            return Pair(ptx, arrayListOf(myOldParty.owningKey))
         }
     }
 
diff --git a/src/test/kotlin/contracts/IRSTests.kt b/src/test/kotlin/contracts/IRSTests.kt
index 01ef8e3203..aec35de105 100644
--- a/src/test/kotlin/contracts/IRSTests.kt
+++ b/src/test/kotlin/contracts/IRSTests.kt
@@ -4,6 +4,7 @@ import core.*
 import core.node.services.DummyTimestampingAuthority
 import core.testutils.*
 import org.junit.Test
+import java.math.BigDecimal
 import java.time.LocalDate
 import java.util.*
 
@@ -15,9 +16,9 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
                     fixedRatePayer = MEGA_CORP,
                     notional = 15900000.DOLLARS,
                     paymentFrequency = Frequency.SemiAnnual,
-                    effectiveDate = LocalDate.of(2016, 3, 16),
+                    effectiveDate = LocalDate.of(2016, 3, 10),
                     effectiveDateAdjustment = null,
-                    terminationDate = LocalDate.of(2026, 3, 16),
+                    terminationDate = LocalDate.of(2026, 3, 10),
                     terminationDateAdjustment = null,
                     fixedRate = FixedRate(PercentageRatioUnit("1.677")),
                     dayCountBasisDay = DayCountBasisDay.D30,
@@ -98,7 +99,6 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
             InterestRateSwap.State(fixedLeg = fixedLeg, floatingLeg = floatingLeg, calculation = calculation, common = common)
         }
         2 -> {
-
             // 10y swap, we pay 1.3% fixed 30/360 semi, rec 3m usd libor act/360 Q on 25m notional (mod foll/adj on both sides)
             // I did a mock up start date 10/03/2015 – 10/03/2025 so you have 5 cashflows on float side that have been preset the rest are unknown
 
@@ -181,7 +181,7 @@ fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
                     addressForTransfers = "",
                     exposure = UnknownType(),
                     localBusinessDay = BusinessCalendar.getInstance("London"),
-                    tradeID = "trade1",
+                    tradeID = "trade2",
                     hashLegalDocs = "put hash here",
                     dailyInterestAmount = Expression("(CashAmount * InterestRate ) / (fixedLeg.notional.currency.currencyCode.equals('GBP')) ? 365 : 360")
             )
@@ -197,10 +197,25 @@ class IRSTests {
 
     val attachments = MockStorageService().attachments
 
+    val exampleIRS = createDummyIRS(1)
+
+    val inState = InterestRateSwap.State(
+            exampleIRS.fixedLeg,
+            exampleIRS.floatingLeg,
+            exampleIRS.calculation,
+            exampleIRS.common
+    )
+
+    val outState = inState.copy()
+
     @Test
     fun ok() {
-        val t = trade()
-        t.verify()
+        trade().verify()
+    }
+
+    @Test
+    fun `ok with groups`() {
+        tradegroups().verify()
     }
 
     /**
@@ -243,7 +258,7 @@ class IRSTests {
     }
 
     /**
-     * Test the generate
+     * Test the generate. No explicit exception as if something goes wrong, we'll find out anyway.
      */
     @Test
     fun generateIRS() {
@@ -251,6 +266,9 @@ class IRSTests {
         generateIRSTxn(1)
     }
 
+    /**
+     * Testing a simple IRS, add a few fixings and then display as CSV
+     */
     @Test
     fun `IRS Export test`() {
         // No transactions etc required - we're just checking simple maths and export functionallity
@@ -351,7 +369,14 @@ class IRSTests {
     }
 
 
+    /**
+     * Generates a typical transactional history for an IRS.
+     */
     fun trade(): TransactionGroupDSL<InterestRateSwap.State> {
+
+        val ld = LocalDate.of(2016, 3, 8)
+        val bd = BigDecimal("0.0063518")
+
         val txgroup: TransactionGroupDSL<InterestRateSwap.State> = transactionGroupFor() {
             transaction("Agreement") {
                 output("irs post agreement") { singleIRS() }
@@ -361,18 +386,349 @@ class IRSTests {
 
             transaction("Fix") {
                 input("irs post agreement")
-                output("irs post first fixing") { "irs post agreement".output }
-                arg(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
-                timestamp(TEST_TX_TIME)
-            }
-
-            transaction("Pay") {
-                input("irs post first fixing")
-                output("irs post first payment") { "irs post first fixing".output }
-                arg(MEGA_CORP_PUBKEY, MINI_CORP_PUBKEY) { InterestRateSwap.Commands.Pay() }
+                output("irs post first fixing") {
+                    "irs post agreement".output.copy(
+                            "irs post agreement".output.fixedLeg,
+                            "irs post agreement".output.floatingLeg,
+                            "irs post agreement".output.calculation.applyFixing(ld, FixedRate(RatioUnit(bd))),
+                            "irs post agreement".output.common
+                    )
+                }
+                arg(ORACLE_PUBKEY) {
+                    InterestRateSwap.Commands.Fix()
+                }
+                arg(ORACLE_PUBKEY) {
+                    Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
+                }
                 timestamp(TEST_TX_TIME)
             }
         }
         return txgroup
     }
-}
\ No newline at end of file
+
+    @Test
+    fun `ensure failure occurs when there are inbound states for an agreement command`() {
+        transaction {
+            input() { singleIRS() }
+            output("irs post agreement") { singleIRS() }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "There are no in states for an agreement"
+        }
+    }
+
+    @Test
+    fun `ensure failure occurs when no events in fix schedule`() {
+        val irs = singleIRS()
+        val emptySchedule = HashMap<LocalDate, FixedRatePaymentEvent>()
+        transaction {
+            output() {
+                irs.copy(calculation = irs.calculation.copy(fixedLegPaymentSchedule = emptySchedule))
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "There are events in the fix schedule"
+        }
+    }
+
+    @Test
+    fun `ensure failure occurs when no events in floating schedule`() {
+        val irs = singleIRS()
+        val emptySchedule = HashMap<LocalDate, FloatingRatePaymentEvent>()
+        transaction {
+            output() {
+                irs.copy(calculation = irs.calculation.copy(floatingLegPaymentSchedule = emptySchedule))
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "There are events in the float schedule"
+        }
+    }
+
+    @Test
+    fun `ensure notionals are non zero`() {
+        val irs = singleIRS()
+        transaction {
+            output() {
+                irs.copy(irs.fixedLeg.copy(notional = irs.fixedLeg.notional.copy(pennies = 0)))
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "All notionals must be non zero"
+        }
+
+        transaction {
+            output() {
+                irs.copy(irs.fixedLeg.copy(notional = irs.floatingLeg.notional.copy(pennies = 0)))
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "All notionals must be non zero"
+        }
+    }
+
+    @Test
+    fun `ensure positive rate on fixed leg`() {
+        val irs = singleIRS()
+        val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(fixedRate = FixedRate(PercentageRatioUnit("-0.1"))))
+        transaction {
+            output() {
+                modifiedIRS
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "The fixed leg rate must be positive"
+        }
+    }
+
+    /**
+     * This will be modified once we adapt the IRS to be cross currency
+     */
+    @Test
+    fun `ensure same currency notionals`() {
+        val irs = singleIRS()
+        val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(notional = Amount(irs.fixedLeg.notional.pennies, Currency.getInstance("JPY"))))
+        transaction {
+            output() {
+                modifiedIRS
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "The currency of the notionals must be the same"
+        }
+    }
+
+    @Test
+    fun `ensure notional amounts are equal`() {
+        val irs = singleIRS()
+        val modifiedIRS = irs.copy(fixedLeg = irs.fixedLeg.copy(notional = Amount(irs.floatingLeg.notional.pennies + 1, irs.floatingLeg.notional.currency)))
+        transaction {
+            output() {
+                modifiedIRS
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "All leg notionals must be the same"
+        }
+    }
+
+    @Test
+    fun `ensure trade date and termination date checks are done pt1`() {
+        val irs = singleIRS()
+        val modifiedIRS1 = irs.copy(fixedLeg = irs.fixedLeg.copy(terminationDate = irs.fixedLeg.effectiveDate.minusDays(1)))
+        transaction {
+            output() {
+                modifiedIRS1
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "The effective date is before the termination date for the fixed leg"
+        }
+
+        val modifiedIRS2 = irs.copy(floatingLeg = irs.floatingLeg.copy(terminationDate = irs.floatingLeg.effectiveDate.minusDays(1)))
+        transaction {
+            output() {
+                modifiedIRS2
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "The effective date is before the termination date for the floating leg"
+        }
+    }
+
+    @Test
+    fun `ensure trade date and termination date checks are done pt2`() {
+        val irs = singleIRS()
+
+        val modifiedIRS3 = irs.copy(floatingLeg = irs.floatingLeg.copy(terminationDate = irs.fixedLeg.terminationDate.minusDays(1)))
+        transaction {
+            output() {
+                modifiedIRS3
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "The termination dates are aligned"
+        }
+
+
+        val modifiedIRS4 = irs.copy(floatingLeg = irs.floatingLeg.copy(effectiveDate = irs.fixedLeg.effectiveDate.minusDays(1)))
+        transaction {
+            output() {
+                modifiedIRS4
+            }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+            this `fails requirement` "The effective dates are aligned"
+        }
+    }
+
+
+    @Test
+    fun `various fixing tests`() {
+
+        val ld = LocalDate.of(2016, 3, 8)
+        val bd = BigDecimal("0.0063518")
+
+        transaction {
+            output("irs post agreement") { singleIRS() }
+            arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+            timestamp(TEST_TX_TIME)
+        }
+
+        val oldIRS = singleIRS(1)
+        val newIRS = oldIRS.copy(oldIRS.fixedLeg,
+                oldIRS.floatingLeg,
+                oldIRS.calculation.applyFixing(ld, FixedRate(RatioUnit(bd))),
+                oldIRS.common)
+
+        transaction {
+            input() {
+                oldIRS
+
+            }
+
+            // Templated tweak for reference. A corrent fixing applied should be ok
+            tweak {
+                arg(ORACLE_PUBKEY) {
+                    InterestRateSwap.Commands.Fix()
+                }
+                timestamp(TEST_TX_TIME)
+                arg(ORACLE_PUBKEY) {
+                    Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
+                }
+                output() { newIRS }
+                this.accepts()
+            }
+
+            // This test makes sure that verify confirms the fixing was applied and there is a difference in the old and new
+            tweak {
+                arg(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
+                timestamp(TEST_TX_TIME)
+                arg(ORACLE_PUBKEY) { Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd) }
+                output() { oldIRS }
+                this`fails requirement` "There is at least one difference in the IRS floating leg payment schedules"
+            }
+
+            // This tests tries to sneak in a change to another fixing (which may or may not be the latest one)
+            tweak {
+                arg(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
+                timestamp(TEST_TX_TIME)
+                arg(ORACLE_PUBKEY) {
+                    Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd)
+                }
+
+                val firstResetKey = newIRS.calculation.floatingLegPaymentSchedule.keys.first()
+                val firstResetValue = newIRS.calculation.floatingLegPaymentSchedule[firstResetKey]
+                var modifiedFirstResetValue = firstResetValue!!.copy(notional = Amount(firstResetValue.notional.pennies, Currency.getInstance("JPY")))
+
+                output() {
+                    newIRS.copy(
+                            newIRS.fixedLeg,
+                            newIRS.floatingLeg,
+                            newIRS.calculation.copy(floatingLegPaymentSchedule = newIRS.calculation.floatingLegPaymentSchedule.plus(
+                                    Pair(firstResetKey, modifiedFirstResetValue))),
+                            newIRS.common
+                    )
+                }
+                this`fails requirement` "There is only one change in the IRS floating leg payment schedule"
+            }
+
+            // This tests modifies the payment currency for the fixing
+            tweak {
+                arg(ORACLE_PUBKEY) { InterestRateSwap.Commands.Fix() }
+                timestamp(TEST_TX_TIME)
+                arg(ORACLE_PUBKEY) { Fix(FixOf("ICE LIBOR", ld, Tenor("3M")), bd) }
+
+                val latestReset = newIRS.calculation.floatingLegPaymentSchedule.filter { it.value.rate is FixedRate }.maxBy { it.key }
+                var modifiedLatestResetValue = latestReset!!.value.copy(notional = Amount(latestReset.value.notional.pennies, Currency.getInstance("JPY")))
+
+                output() {
+                    newIRS.copy(
+                            newIRS.fixedLeg,
+                            newIRS.floatingLeg,
+                            newIRS.calculation.copy(floatingLegPaymentSchedule = newIRS.calculation.floatingLegPaymentSchedule.plus(
+                                    Pair(latestReset.key, modifiedLatestResetValue))),
+                            newIRS.common
+                    )
+                }
+                this`fails requirement` "The fix payment has the same currency as the notional"
+            }
+        }
+    }
+
+
+    /**
+     * This returns an example of transactions that are grouped by TradeId and then a fixing applied.
+     * It's important to make the tradeID different for two reasons, the hashes will be the same and all sorts of confusion will
+     * result and the grouping won't work either.
+     * In reality, the only fields that should be in common will be the next fixing date and the reference rate.
+     */
+    fun tradegroups(): TransactionGroupDSL<InterestRateSwap.State> {
+        val ld1 = LocalDate.of(2016, 3, 8)
+        val bd1 = BigDecimal("0.0063518")
+
+        val irs = singleIRS()
+
+        val txgroup: TransactionGroupDSL<InterestRateSwap.State> = transactionGroupFor() {
+            transaction("Agreement") {
+                output("irs post agreement1") {
+                    irs.copy(
+                            irs.fixedLeg,
+                            irs.floatingLeg,
+                            irs.calculation,
+                            irs.common.copy(tradeID = "t1")
+
+                    )
+                }
+                arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+                timestamp(TEST_TX_TIME)
+            }
+
+            transaction("Agreement") {
+                output("irs post agreement2") {
+                    irs.copy(
+                            irs.fixedLeg,
+                            irs.floatingLeg,
+                            irs.calculation,
+                            irs.common.copy(tradeID = "t2")
+
+                    )
+                }
+                arg(MEGA_CORP_PUBKEY) { InterestRateSwap.Commands.Agree() }
+                timestamp(TEST_TX_TIME)
+            }
+
+            transaction("Fix") {
+                input("irs post agreement1")
+                input("irs post agreement2")
+                output("irs post first fixing1") {
+                    "irs post agreement1".output.copy(
+                            "irs post agreement1".output.fixedLeg,
+                            "irs post agreement1".output.floatingLeg,
+                            "irs post agreement1".output.calculation.applyFixing(ld1, FixedRate(RatioUnit(bd1))),
+                            "irs post agreement1".output.common.copy(tradeID = "t1")
+                    )
+                }
+                output("irs post first fixing2") {
+                    "irs post agreement2".output.copy(
+                            "irs post agreement2".output.fixedLeg,
+                            "irs post agreement2".output.floatingLeg,
+                            "irs post agreement2".output.calculation.applyFixing(ld1, FixedRate(RatioUnit(bd1))),
+                            "irs post agreement2".output.common.copy(tradeID = "t2")
+                    )
+                }
+
+                arg(ORACLE_PUBKEY) {
+                    InterestRateSwap.Commands.Fix()
+                }
+                arg(ORACLE_PUBKEY) {
+                    Fix(FixOf("ICE LIBOR", ld1, Tenor("3M")), bd1)
+                }
+                timestamp(TEST_TX_TIME)
+            }
+        }
+        return txgroup
+    }
+}
+
+
diff --git a/src/test/kotlin/core/testutils/TestUtils.kt b/src/test/kotlin/core/testutils/TestUtils.kt
index fa5d705dc8..3cead9ae75 100644
--- a/src/test/kotlin/core/testutils/TestUtils.kt
+++ b/src/test/kotlin/core/testutils/TestUtils.kt
@@ -157,16 +157,16 @@ open class TransactionForTest : AbstractTransactionForTest() {
     private val inStates = arrayListOf<ContractState>()
     fun input(s: () -> ContractState) = inStates.add(s())
 
-    protected fun run(time: Instant) {
+    protected fun runCommandsAndVerify(time: Instant) {
         val cmds = commandsToAuthenticatedObjects()
         val tx = TransactionForVerification(inStates, outStates.map { it.state }, emptyList(), cmds, SecureHash.randomSHA256())
         tx.verify()
     }
 
-    fun accepts(time: Instant = TEST_TX_TIME) = run(time)
+    fun accepts(time: Instant = TEST_TX_TIME) = runCommandsAndVerify(time)
     fun rejects(withMessage: String? = null, time: Instant = TEST_TX_TIME) {
         val r = try {
-            run(time)
+            runCommandsAndVerify(time)
             false
         } catch (e: Exception) {
             val m = e.message
@@ -179,7 +179,9 @@ open class TransactionForTest : AbstractTransactionForTest() {
         if (!r) throw AssertionError("Expected exception but didn't get one")
     }
 
-    // which is uglier?? :)
+    /**
+     * Used to confirm that the test, when (implicitly) run against the .verify() method, fails with the text of the message
+     */
     infix fun `fails requirement`(msg: String) = rejects(msg)
 
     fun fails_requirement(msg: String) = this.`fails requirement`(msg)