Universal: example parties renamed

This commit is contained in:
sofusmortensen 2016-09-07 10:42:39 +02:00
parent 1ceee48696
commit c7b164897b
10 changed files with 125 additions and 130 deletions

View File

@ -12,7 +12,6 @@ import java.util.*
interface Arrangement interface Arrangement
// A base arrangement with no rights and no obligations. Contract cancellation/termination is a transition to ``Zero``. // A base arrangement with no rights and no obligations. Contract cancellation/termination is a transition to ``Zero``.
class Zero() : Arrangement { class Zero() : Arrangement {
override fun hashCode(): Int { override fun hashCode(): Int {
@ -28,11 +27,7 @@ class Zero() : Arrangement {
// //
// todo: should be replaced with something that uses Corda assets and/or cash? // todo: should be replaced with something that uses Corda assets and/or cash?
// todo: should only be allowed to transfer non-negative amounts // todo: should only be allowed to transfer non-negative amounts
data class Transfer(val amount: Perceivable<BigDecimal>, val currency: Currency, val from: Party, val to: Party) : Arrangement { data class Transfer(val amount: Perceivable<BigDecimal>, val currency: Currency, val from: Party, val to: Party) : Arrangement
constructor(amount: BigDecimal, currency: Currency, from: Party, to: Party ) : this(const(amount), currency, from, to)
constructor(amount: Amount<Currency>, from: Party, to: Party ) : this(const(BigDecimal(amount.quantity)), amount.token, from, to)
}
// A combinator over a list of arrangements. Each arrangement in list will create a separate independent arrangement state. // A combinator over a list of arrangements. Each arrangement in list will create a separate independent arrangement state.
// The ``And`` combinator cannot be root in a arrangement. // The ``And`` combinator cannot be root in a arrangement.

View File

@ -141,7 +141,7 @@ class UniversalContract : Contract {
is Transfer -> { is Transfer -> {
val amount = eval(tx, arrangement.amount) val amount = eval(tx, arrangement.amount)
requireThat { "transferred quantity is non-negative" by (amount >= BigDecimal.ZERO) } requireThat { "transferred quantity is non-negative" by (amount >= BigDecimal.ZERO) }
Transfer(amount, arrangement.currency, arrangement.from, arrangement.to) Transfer(const(amount), arrangement.currency, arrangement.from, arrangement.to)
} }
is And -> And(arrangement.arrangements.map { validateImmediateTransfers(tx, it) }.toSet()) is And -> And(arrangement.arrangements.map { validateImmediateTransfers(tx, it) }.toSet())
else -> arrangement else -> arrangement

View File

@ -24,7 +24,7 @@ open class ContractBuilder {
val contracts = mutableListOf<Arrangement>() val contracts = mutableListOf<Arrangement>()
fun Party.gives(beneficiary: Party, amount: BigDecimal, currency: Currency) : Transfer { fun Party.gives(beneficiary: Party, amount: BigDecimal, currency: Currency) : Transfer {
val c = Transfer(amount, currency, this, beneficiary) val c = Transfer(const(amount), currency, this, beneficiary)
contracts.add( c ) contracts.add( c )
return c return c
} }

View File

@ -20,14 +20,14 @@ class Cap {
val contract = arrange { val contract = arrange {
rollOut("2016-04-01", "2017-04-01", Frequency.Quarterly) { rollOut("2016-04-01", "2017-04-01", Frequency.Quarterly) {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"exercise".anytime { "exercise".anytime {
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end) val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end)
val fixed = interest(notional, "act/365", 0.5.bd, start, end) val fixed = interest(notional, "act/365", 0.5.bd, start, end)
wileECoyote.gives(roadRunner, floating - fixed, currency) highStreetBank.gives(acmeCorp, floating - fixed, currency)
next() next()
} }
} or roadRunner.may { } or acmeCorp.may {
"skip".anytime { "skip".anytime {
next() next()
} }
@ -42,15 +42,15 @@ class Cap {
rollOut("2016-04-01", "2017-04-01", Frequency.Quarterly, object { rollOut("2016-04-01", "2017-04-01", Frequency.Quarterly, object {
val limit = variable(150.K) val limit = variable(150.K)
}) { }) {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"exercise".anytime { "exercise".anytime {
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end) val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("6M")), start, end)
val fixed = interest(notional, "act/365", 0.5.bd, start, end) val fixed = interest(notional, "act/365", 0.5.bd, start, end)
val payout = (floating - fixed).plus() val payout = (floating - fixed).plus()
wileECoyote.gives(roadRunner, payout, currency) highStreetBank.gives(acmeCorp, payout, currency)
next(vars.limit to vars.limit - payout) next(vars.limit to vars.limit - payout)
} }
} or roadRunner.may { } or acmeCorp.may {
"skip".anytime { "skip".anytime {
next() next()
} }
@ -67,11 +67,11 @@ class Cap {
this `fails with` "transaction has a single command" this `fails with` "transaction has a single command"
tweak { tweak {
command(roadRunner.owningKey) { UniversalContract.Commands.Issue() } command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() }
this `fails with` "the transaction is signed by all liable parties" this `fails with` "the transaction is signed by all liable parties"
} }
command(wileECoyote.owningKey) { UniversalContract.Commands.Issue() } command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() }
this.verifies() this.verifies()
} }

View File

@ -24,26 +24,26 @@ class Caplet {
val currency = EUR val currency = EUR
val contract = arrange { val contract = arrange {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"exercise".anytime() { "exercise".anytime() {
val floating = interest(notional, "act/365", fix("LIBOR", dt, Tenor("6M")), "2016-04-01", "2016-10-01") val floating = interest(notional, "act/365", fix("LIBOR", dt, Tenor("6M")), "2016-04-01", "2016-10-01")
val fixed = interest(notional, "act/365", 0.5.bd, "2016-04-01", "2016-10-01") val fixed = interest(notional, "act/365", 0.5.bd, "2016-04-01", "2016-10-01")
wileECoyote.gives(roadRunner, (floating - fixed).plus(), currency) highStreetBank.gives(acmeCorp, (floating - fixed).plus(), currency)
} }
} }
} }
val contractFixed = arrange { val contractFixed = arrange {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"exercise".anytime() { "exercise".anytime() {
val floating = interest(notional, "act/365", 1.0.bd, "2016-04-01", "2016-10-01") val floating = interest(notional, "act/365", 1.0.bd, "2016-04-01", "2016-10-01")
val fixed = interest(notional, "act/365", 0.5.bd, "2016-04-01", "2016-10-01") val fixed = interest(notional, "act/365", 0.5.bd, "2016-04-01", "2016-10-01")
wileECoyote.gives(roadRunner, (floating - fixed).plus(), currency) highStreetBank.gives(acmeCorp, (floating - fixed).plus(), currency)
} }
} }
} }
val contractFinal = arrange { wileECoyote.gives(roadRunner, 250.K, EUR) } val contractFinal = arrange { highStreetBank.gives(acmeCorp, 250.K, EUR) }
val stateStart = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contract) val stateStart = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contract)
@ -60,11 +60,11 @@ class Caplet {
this `fails with` "transaction has a single command" this `fails with` "transaction has a single command"
tweak { tweak {
command(roadRunner.owningKey) { UniversalContract.Commands.Issue() } command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() }
this `fails with` "the transaction is signed by all liable parties" this `fails with` "the transaction is signed by all liable parties"
} }
command(wileECoyote.owningKey) { UniversalContract.Commands.Issue() } command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() }
this.verifies() this.verifies()
} }
@ -78,11 +78,11 @@ class Caplet {
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
tweak { tweak {
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") }
this `fails with` "action must be defined" this `fails with` "action must be defined"
} }
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("exercise") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("exercise") }
this.verifies() this.verifies()
} }
@ -96,38 +96,38 @@ class Caplet {
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
tweak { tweak {
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") }
this `fails with` "action must be defined" this `fails with` "action must be defined"
} }
tweak { tweak {
// wrong source // wrong source
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", dt, Tenor("6M")), 1.0.bd))) } command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", dt, Tenor("6M")), 1.0.bd))) }
this `fails with` "relevant fixing must be included" this `fails with` "relevant fixing must be included"
} }
tweak { tweak {
// wrong date // wrong date
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt.plusYears(1), Tenor("6M")), 1.0.bd))) } command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt.plusYears(1), Tenor("6M")), 1.0.bd))) }
this `fails with` "relevant fixing must be included" this `fails with` "relevant fixing must be included"
} }
tweak { tweak {
// wrong tenor // wrong tenor
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("3M")), 1.0.bd))) } command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("3M")), 1.0.bd))) }
this `fails with` "relevant fixing must be included" this `fails with` "relevant fixing must be included"
} }
tweak { tweak {
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), 1.5.bd))) } command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), 1.5.bd))) }
this `fails with` "output state does not reflect fix command" this `fails with` "output state does not reflect fix command"
} }
command(wileECoyote.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), 1.0.bd))) } command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", dt, Tenor("6M")), 1.0.bd))) }
this.verifies() this.verifies()
} }

View File

@ -10,9 +10,9 @@ import java.util.*
*/ */
// Test parties // Test parties
val roadRunner = Party("Road Runner", generateKeyPair().public) val acmeCorp = Party("ACME Corporation", generateKeyPair().public)
val wileECoyote = Party("Wile E. Coyote", generateKeyPair().public) val highStreetBank = Party("High Street Bank", generateKeyPair().public)
val porkyPig = Party("Porky Pig", generateKeyPair().public) val momAndPop = Party("Mom and Pop", generateKeyPair().public)
val acmeCorporationHasDefaulted = DummyPerceivable<Boolean>() val acmeCorporationHasDefaulted = DummyPerceivable<Boolean>()
@ -28,11 +28,11 @@ class ContractDefinition {
val cds_contract = arrange { val cds_contract = arrange {
roadRunner.may { acmeCorp.may {
"payout".givenThat(acmeCorporationHasDefaulted and before("2017-09-01")) { "payout".givenThat(acmeCorporationHasDefaulted and before("2017-09-01")) {
wileECoyote.gives(roadRunner, 1.M, USD) highStreetBank.gives(acmeCorp, 1.M, USD)
} }
} or wileECoyote.may { } or highStreetBank.may {
"expire".givenThat(after("2017-09-01")) { "expire".givenThat(after("2017-09-01")) {
zero zero
} }
@ -41,12 +41,12 @@ class ContractDefinition {
val american_fx_option = arrange { val american_fx_option = arrange {
roadRunner.may { acmeCorp.may {
"exercise".anytime { "exercise".anytime {
wileECoyote.gives(roadRunner, 1.M, EUR) highStreetBank.gives(acmeCorp, 1.M, EUR)
roadRunner.gives(wileECoyote, 1200.K, USD) acmeCorp.gives(highStreetBank, 1200.K, USD)
} }
} or wileECoyote.may { } or highStreetBank.may {
"expire".givenThat(after("2017-09-01")) { "expire".givenThat(after("2017-09-01")) {
zero zero
} }
@ -55,16 +55,16 @@ class ContractDefinition {
val european_fx_option = arrange { val european_fx_option = arrange {
roadRunner.may { acmeCorp.may {
"exercise".anytime { "exercise".anytime {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"execute".givenThat(after("2017-09-01")) { "execute".givenThat(after("2017-09-01")) {
wileECoyote.gives(roadRunner, 1.M, EUR) highStreetBank.gives(acmeCorp, 1.M, EUR)
roadRunner.gives(wileECoyote, 1200.K, USD) acmeCorp.gives(highStreetBank, 1200.K, USD)
} }
} }
} }
} or wileECoyote.may { } or highStreetBank.may {
"expire".givenThat(after("2017-09-01")) { "expire".givenThat(after("2017-09-01")) {
zero zero
} }

View File

@ -15,23 +15,23 @@ class FXSwap {
val TEST_TX_TIME_TOO_EARLY: Instant get() = Instant.parse("2017-08-31T12:00:00.00Z") val TEST_TX_TIME_TOO_EARLY: Instant get() = Instant.parse("2017-08-31T12:00:00.00Z")
val contract = arrange { val contract = arrange {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"execute".givenThat(after("2017-09-01")) { "execute".givenThat(after("2017-09-01")) {
wileECoyote.gives(roadRunner, 1200.K, USD) highStreetBank.gives(acmeCorp, 1200.K, USD)
roadRunner.gives(wileECoyote, 1.M, EUR) acmeCorp.gives(highStreetBank, 1.M, EUR)
} }
} }
} }
val transfer1 = arrange { wileECoyote.gives(roadRunner, 1200.K, USD) } val transfer1 = arrange { highStreetBank.gives(acmeCorp, 1200.K, USD) }
val transfer2 = arrange { roadRunner.gives(wileECoyote, 1.M, EUR) } val transfer2 = arrange { acmeCorp.gives(highStreetBank, 1.M, EUR) }
val outState1 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer1 ) val outState1 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer1 )
val outState2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer2 ) val outState2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transfer2 )
val transferBad1 = arrange { wileECoyote.gives(roadRunner, 1200.K, GBP) } // wrong currency val transferBad1 = arrange { highStreetBank.gives(acmeCorp, 1200.K, GBP) } // wrong currency
val transferBad2 = arrange { roadRunner.gives(wileECoyote, 900.K, EUR) } // wrong amount val transferBad2 = arrange { acmeCorp.gives(highStreetBank, 900.K, EUR) } // wrong amount
val transferBad3 = arrange { wileECoyote.gives(wileECoyote, 1.M, EUR) } // wrong party val transferBad3 = arrange { highStreetBank.gives(highStreetBank, 1.M, EUR) } // wrong party
val outStateBad1 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transferBad1 ) val outStateBad1 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transferBad1 )
val outStateBad2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transferBad2 ) val outStateBad2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), transferBad2 )
@ -49,15 +49,15 @@ class FXSwap {
this `fails with` "transaction has a single command" this `fails with` "transaction has a single command"
tweak { tweak {
command(roadRunner.owningKey) { UniversalContract.Commands.Issue() } command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() }
this `fails with` "the transaction is signed by all liable parties" this `fails with` "the transaction is signed by all liable parties"
} }
tweak { tweak {
command(wileECoyote.owningKey) { UniversalContract.Commands.Issue() } command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() }
this `fails with` "the transaction is signed by all liable parties" this `fails with` "the transaction is signed by all liable parties"
} }
command(wileECoyote.owningKey, roadRunner.owningKey) { UniversalContract.Commands.Issue() } command(highStreetBank.owningKey, acmeCorp.owningKey) { UniversalContract.Commands.Issue() }
this.verifies() this.verifies()
} }
@ -72,11 +72,11 @@ class FXSwap {
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
tweak { tweak {
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") }
this `fails with` "action must be defined" this `fails with` "action must be defined"
} }
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("execute") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("execute") }
this.verifies() this.verifies()
} }
@ -91,11 +91,11 @@ class FXSwap {
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
tweak { tweak {
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") }
this `fails with` "action must be defined" this `fails with` "action must be defined"
} }
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("execute") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("execute") }
this.verifies() this.verifies()
} }
@ -109,7 +109,7 @@ class FXSwap {
output { outState2 } output { outState2 }
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
command(porkyPig.owningKey) { UniversalContract.Commands.Action("execute") } command(momAndPop.owningKey) { UniversalContract.Commands.Action("execute") }
this `fails with` "action must be authorized" this `fails with` "action must be authorized"
} }
} }
@ -122,7 +122,7 @@ class FXSwap {
output { outState2 } output { outState2 }
timestamp(TEST_TX_TIME_TOO_EARLY) timestamp(TEST_TX_TIME_TOO_EARLY)
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") } command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") }
this `fails with` "condition must be met" this `fails with` "condition must be met"
} }
} }
@ -134,7 +134,7 @@ class FXSwap {
output { outState1 } output { outState1 }
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") } command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") }
this `fails with` "output state must match action result state" this `fails with` "output state must match action result state"
} }
} }
@ -147,7 +147,7 @@ class FXSwap {
output { outStateBad2 } output { outStateBad2 }
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") } command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") }
this `fails with` "output states must match action result state" this `fails with` "output states must match action result state"
} }
} }
@ -160,7 +160,7 @@ class FXSwap {
output { outState2 } output { outState2 }
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") } command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") }
this `fails with` "output states must match action result state" this `fails with` "output states must match action result state"
} }
} }
@ -173,7 +173,7 @@ class FXSwap {
output { outStateBad3 } output { outStateBad3 }
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") } command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") }
this `fails with` "output states must match action result state" this `fails with` "output states must match action result state"
} }
} }

View File

@ -17,28 +17,28 @@ class Swaption {
val coupon = 1.5.bd val coupon = 1.5.bd
val dreary_contract = arrange { val dreary_contract = arrange {
(wileECoyote or roadRunner).may { (highStreetBank or acmeCorp).may {
"proceed".givenThat(after("01/07/2015")) { "proceed".givenThat(after("01/07/2015")) {
wileECoyote.gives(roadRunner, libor(notional, "01/04/2015", "01/07/2015"), currency) highStreetBank.gives(acmeCorp, libor(notional, "01/04/2015", "01/07/2015"), currency)
roadRunner.gives(wileECoyote, interest(notional, "act/365", coupon, "01/04/2015", "01/07/2015"), currency) acmeCorp.gives(highStreetBank, interest(notional, "act/365", coupon, "01/04/2015", "01/07/2015"), currency)
(wileECoyote or roadRunner).may { (highStreetBank or acmeCorp).may {
"proceed".givenThat(after("01/10/2015")) { "proceed".givenThat(after("01/10/2015")) {
wileECoyote.gives(roadRunner, libor(notional, "01/07/2015", "01/10/2015"), currency) highStreetBank.gives(acmeCorp, libor(notional, "01/07/2015", "01/10/2015"), currency)
roadRunner.gives(wileECoyote, interest(notional, "act/365", coupon, "01/07/2015", "01/10/2015"), currency) acmeCorp.gives(highStreetBank, interest(notional, "act/365", coupon, "01/07/2015", "01/10/2015"), currency)
(wileECoyote or roadRunner).may { (highStreetBank or acmeCorp).may {
// etc ... // etc ...
} }
} }
} or roadRunner.may { } or acmeCorp.may {
"cancel".anytime { "cancel".anytime {
roadRunner.gives(wileECoyote, 10.K, USD) acmeCorp.gives(highStreetBank, 10.K, USD)
} }
} }
} }
} or roadRunner.may { } or acmeCorp.may {
"cancel".anytime { "cancel".anytime {
roadRunner.gives(wileECoyote, 10.K, USD) acmeCorp.gives(highStreetBank, 10.K, USD)
} }
} }
} }
@ -46,15 +46,15 @@ class Swaption {
val elegant_contract = arrange { val elegant_contract = arrange {
rollOut("01/04/2015", "01/04/2025", Frequency.Quarterly) { rollOut("01/04/2015", "01/04/2025", Frequency.Quarterly) {
(wileECoyote or roadRunner).may { (highStreetBank or acmeCorp).may {
"proceed".givenThat(after(start)) { "proceed".givenThat(after(start)) {
wileECoyote.gives(roadRunner, libor(notional, start, end), currency) highStreetBank.gives(acmeCorp, libor(notional, start, end), currency)
roadRunner.gives(wileECoyote, interest(notional, "act/365", coupon, start, end), currency) acmeCorp.gives(highStreetBank, interest(notional, "act/365", coupon, start, end), currency)
next() next()
} }
} or roadRunner.may { } or acmeCorp.may {
"cancel".anytime { "cancel".anytime {
roadRunner.gives(wileECoyote, 10.K, currency) acmeCorp.gives(highStreetBank, 10.K, currency)
} }
} }
} }
@ -66,18 +66,18 @@ class Swaption {
rollOut("01/04/2015", "01/04/2016", Frequency.Quarterly, object { rollOut("01/04/2015", "01/04/2016", Frequency.Quarterly, object {
val cap = variable(150.K) val cap = variable(150.K)
}) { }) {
roadRunner.may { acmeCorp.may {
"exercise".givenThat(before(end)) { "exercise".givenThat(before(end)) {
val payout = (EUR / USD - strike).plus() * notional val payout = (EUR / USD - strike).plus() * notional
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"proceed".givenThat(after(end)) { "proceed".givenThat(after(end)) {
wileECoyote.gives(roadRunner, payout, USD) highStreetBank.gives(acmeCorp, payout, USD)
next(vars.cap to vars.cap - payout) next(vars.cap to vars.cap - payout)
} }
} }
} }
} or (roadRunner or wileECoyote).may { } or (acmeCorp or highStreetBank).may {
"proceedWithoutExercise".givenThat(after(end)) { "proceedWithoutExercise".givenThat(after(end)) {
next() next()
} }
@ -89,18 +89,18 @@ class Swaption {
rollOut("01/04/2015", "01/04/2016", Frequency.Quarterly, object { rollOut("01/04/2015", "01/04/2016", Frequency.Quarterly, object {
val uses = variable(4) val uses = variable(4)
}) { }) {
roadRunner.may { acmeCorp.may {
"exercise".givenThat(before(end)) { "exercise".givenThat(before(end)) {
val payout = (EUR / USD - strike).plus() * notional val payout = (EUR / USD - strike).plus() * notional
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"proceed".givenThat(after(end)) { "proceed".givenThat(after(end)) {
wileECoyote.gives(roadRunner, payout, currency) highStreetBank.gives(acmeCorp, payout, currency)
next(vars.uses to vars.uses - 1) next(vars.uses to vars.uses - 1)
} }
} }
} }
} or (roadRunner or wileECoyote).may { } or (acmeCorp or highStreetBank).may {
"proceedWithoutExercise".givenThat(after(end)) { "proceedWithoutExercise".givenThat(after(end)) {
next() next()
} }

View File

@ -12,26 +12,26 @@ import java.time.Instant
class ZeroCouponBond { class ZeroCouponBond {
val contract = arrange { val contract = arrange {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"execute".givenThat(after("2017-09-01")) { "execute".givenThat(after("2017-09-01")) {
wileECoyote.gives(roadRunner, 100.K, GBP) highStreetBank.gives(acmeCorp, 100.K, GBP)
} }
} }
} }
val contractMove = arrange { val contractMove = arrange {
(porkyPig or wileECoyote).may { (momAndPop or highStreetBank).may {
"execute".givenThat(after("2017-09-01")) { "execute".givenThat(after("2017-09-01")) {
wileECoyote.gives(porkyPig, 100.K, GBP) highStreetBank.gives(momAndPop, 100.K, GBP)
} }
} }
} }
val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z") val TEST_TX_TIME_1: Instant get() = Instant.parse("2017-09-02T12:00:00.00Z")
val transfer = arrange { wileECoyote.gives(roadRunner, 100.K, GBP) } val transfer = arrange { highStreetBank.gives(acmeCorp, 100.K, GBP) }
val transferWrong = arrange { wileECoyote.gives(roadRunner, 80.K, GBP) } val transferWrong = arrange { highStreetBank.gives(acmeCorp, 80.K, GBP) }
val inState = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contract ) val inState = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contract )
@ -55,11 +55,11 @@ class ZeroCouponBond {
this `fails with` "transaction has a single command" this `fails with` "transaction has a single command"
tweak { tweak {
command(roadRunner.owningKey) { UniversalContract.Commands.Issue() } command(acmeCorp.owningKey) { UniversalContract.Commands.Issue() }
this `fails with` "the transaction is signed by all liable parties" this `fails with` "the transaction is signed by all liable parties"
} }
command(wileECoyote.owningKey) { UniversalContract.Commands.Issue() } command(highStreetBank.owningKey) { UniversalContract.Commands.Issue() }
this.verifies() this.verifies()
} }
@ -73,11 +73,11 @@ class ZeroCouponBond {
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
tweak { tweak {
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("some undefined name") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") }
this `fails with` "action must be defined" this `fails with` "action must be defined"
} }
command(wileECoyote.owningKey) { UniversalContract.Commands.Action("execute") } command(highStreetBank.owningKey) { UniversalContract.Commands.Action("execute") }
this.verifies() this.verifies()
} }
@ -90,7 +90,7 @@ class ZeroCouponBond {
output { outState } output { outState }
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
command(porkyPig.owningKey) { UniversalContract.Commands.Action("execute") } command(momAndPop.owningKey) { UniversalContract.Commands.Action("execute") }
this `fails with` "action must be authorized" this `fails with` "action must be authorized"
} }
} }
@ -102,7 +102,7 @@ class ZeroCouponBond {
output { outStateWrong } output { outStateWrong }
timestamp(TEST_TX_TIME_1) timestamp(TEST_TX_TIME_1)
command(roadRunner.owningKey) { UniversalContract.Commands.Action("execute") } command(acmeCorp.owningKey) { UniversalContract.Commands.Action("execute") }
this `fails with` "output state must match action result state" this `fails with` "output state must match action result state"
} }
} }
@ -114,24 +114,24 @@ class ZeroCouponBond {
tweak { tweak {
output { outStateMove } output { outStateMove }
command(roadRunner.owningKey) { command(acmeCorp.owningKey) {
UniversalContract.Commands.Move(roadRunner, porkyPig) UniversalContract.Commands.Move(acmeCorp, momAndPop)
} }
this `fails with` "the transaction is signed by all liable parties" this `fails with` "the transaction is signed by all liable parties"
} }
tweak { tweak {
output { inState } output { inState }
command(roadRunner.owningKey, porkyPig.owningKey, wileECoyote.owningKey) { command(acmeCorp.owningKey, momAndPop.owningKey, highStreetBank.owningKey) {
UniversalContract.Commands.Move(roadRunner, porkyPig) UniversalContract.Commands.Move(acmeCorp, momAndPop)
} }
this `fails with` "output state does not reflect move command" this `fails with` "output state does not reflect move command"
} }
output { outStateMove} output { outStateMove}
command(roadRunner.owningKey, porkyPig.owningKey, wileECoyote.owningKey) { command(acmeCorp.owningKey, momAndPop.owningKey, highStreetBank.owningKey) {
UniversalContract.Commands.Move(roadRunner, porkyPig) UniversalContract.Commands.Move(acmeCorp, momAndPop)
} }
this.verifies() this.verifies()
} }

View File

@ -14,9 +14,9 @@ import java.util.*
// various example arrangements using basic syntax // various example arrangements using basic syntax
val cds_contract = arrange { val cds_contract = arrange {
roadRunner.may { acmeCorp.may {
"claim".givenThat(acmeCorporationHasDefaulted and before("2017-09-01")) { "claim".givenThat(acmeCorporationHasDefaulted and before("2017-09-01")) {
wileECoyote.gives(roadRunner, 1.M, USD) highStreetBank.gives(acmeCorp, 1.M, USD)
} }
} }
} }
@ -24,29 +24,29 @@ val cds_contract = arrange {
// fx swap // fx swap
// both parties have the right to trigger the exchange of cash flows // both parties have the right to trigger the exchange of cash flows
val an_fx_swap = arrange { val an_fx_swap = arrange {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"execute".givenThat(after("2017-09-01")) { "execute".givenThat(after("2017-09-01")) {
wileECoyote.gives(roadRunner, 1200.K, USD) highStreetBank.gives(acmeCorp, 1200.K, USD)
roadRunner.gives(wileECoyote, 1.M, EUR) acmeCorp.gives(highStreetBank, 1.M, EUR)
} }
} }
} }
val american_fx_option = arrange { val american_fx_option = arrange {
roadRunner.may { acmeCorp.may {
"exercise".givenThat(before("2017-09-01")) { "exercise".givenThat(before("2017-09-01")) {
wileECoyote.gives(roadRunner, 1200.K, USD) highStreetBank.gives(acmeCorp, 1200.K, USD)
roadRunner.gives(wileECoyote, 1.M, EUR) acmeCorp.gives(highStreetBank, 1.M, EUR)
} }
} }
} }
val european_fx_option = arrange { val european_fx_option = arrange {
roadRunner.may { acmeCorp.may {
"exercise".givenThat(before("2017-09-01")) { "exercise".givenThat(before("2017-09-01")) {
fx_swap("2017-09-01", 1.M, 1.2.bd, EUR, USD, roadRunner, wileECoyote) fx_swap("2017-09-01", 1.M, 1.2.bd, EUR, USD, acmeCorp, highStreetBank)
} }
} or (roadRunner or wileECoyote).may { } or (acmeCorp or highStreetBank).may {
"expire".anytime { "expire".anytime {
zero zero
} }
@ -54,18 +54,18 @@ val european_fx_option = arrange {
} }
val zero_coupon_bond_1 = arrange { val zero_coupon_bond_1 = arrange {
roadRunner.may { acmeCorp.may {
"execute".givenThat(after("2017-09-01")) { "execute".givenThat(after("2017-09-01")) {
wileECoyote.gives(roadRunner, 1.M, USD) highStreetBank.gives(acmeCorp, 1.M, USD)
} }
} }
} }
// maybe in the presence of negative interest rates you would want other side of contract to be able to take initiative as well // maybe in the presence of negative interest rates you would want other side of contract to be able to take initiative as well
val zero_coupon_bond_2 = arrange { val zero_coupon_bond_2 = arrange {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"execute".givenThat(after("2017-09-01")) { "execute".givenThat(after("2017-09-01")) {
wileECoyote.gives(roadRunner, 1.M, USD) highStreetBank.gives(acmeCorp, 1.M, USD)
} }
} }
} }
@ -80,23 +80,23 @@ val zero_coupon_bond_2 = arrange {
// Assume observable is using FX fixing // Assume observable is using FX fixing
// //
val no_touch = arrange { val no_touch = arrange {
(roadRunner or wileECoyote).may { (acmeCorp or highStreetBank).may {
"execute".givenThat(after("2017-09-01")) { "execute".givenThat(after("2017-09-01")) {
wileECoyote.gives(roadRunner, 1.M, USD) highStreetBank.gives(acmeCorp, 1.M, USD)
} }
} or wileECoyote.may { } or highStreetBank.may {
"knock out".givenThat(EUR/USD gt 1.3) "knock out".givenThat(EUR/USD gt 1.3)
} }
} }
val one_touch = arrange { val one_touch = arrange {
wileECoyote.may { highStreetBank.may {
"expire".givenThat(after("2017-09-01")) { "expire".givenThat(after("2017-09-01")) {
zero zero
} }
} or roadRunner.may { } or acmeCorp.may {
"knock in".givenThat(EUR / USD gt 1.3) { "knock in".givenThat(EUR / USD gt 1.3) {
wileECoyote.gives(roadRunner, 1.M, USD) highStreetBank.gives(acmeCorp, 1.M, USD)
} }
} }
} }