mirror of
https://github.com/corda/corda.git
synced 2025-02-21 01:42:24 +00:00
Contracts: Rename ComedyPaper to CommercialPaper and rewrite the comment at the top to flag its not-realistic status.
This commit is contained in:
parent
379d531cf0
commit
d1a605de6f
@ -5,10 +5,14 @@ import java.security.PublicKey
|
||||
import java.time.Instant
|
||||
|
||||
/**
|
||||
* "Comedy paper" is basically like commercial paper, but modelled by a non-expert and without any attention paid
|
||||
* to the issuance aspect. It has a weird name to emphasise that it's not a prototype of real CP, as that's currently
|
||||
* waiting for Jo/Ayoub to deliver full CP use case models. This file may be renamed later if it grows up and
|
||||
* becomes real CP.
|
||||
* This is an ultra-trivial implementation of commercial paper, which is essentially a simpler version of a corporate
|
||||
* bond. It can be seen as a company-specific currency. A company issues CP with a particular face value, like $100
|
||||
* but sells it for less, say $90. The paper can be redeemed for cash at a given date in the future. Thus this example
|
||||
* would have a 10% interest rate with a single repayment. Commercial paper is often rolled out (redeemed and the
|
||||
* money used to immediately rebuy).
|
||||
*
|
||||
* This contract is not intended to realistically model CP. It is here only to act as a next step up above cash in
|
||||
* the prototyping phase. It is thus very incomplete.
|
||||
*
|
||||
* Open issues:
|
||||
* - In this model, you cannot merge or split CP. Can you do this normally? We could model CP as a specialised form
|
||||
@ -17,13 +21,11 @@ import java.time.Instant
|
||||
* issue: need to find a cleaner way to allow this. Does the single-execution-per-transaction model make sense?
|
||||
*/
|
||||
|
||||
// TODO: This is very incomplete! Do not attempt to find mistakes in it just yet.
|
||||
|
||||
val CP_PROGRAM_ID = SecureHash.sha256("comedy-paper")
|
||||
val CP_PROGRAM_ID = SecureHash.sha256("replace-me-later-with-bytecode-hash")
|
||||
|
||||
// TODO: Generalise the notion of an owned instrument into a superclass/supercontract. Consider composition vs inheritance.
|
||||
object ComedyPaper : Contract {
|
||||
override val legalContractReference: String = "https://www.gotlines.com/jokes/1"
|
||||
object CommercialPaper : Contract {
|
||||
override val legalContractReference: String = "https://en.wikipedia.org/wiki/Commercial_paper"
|
||||
|
||||
data class State(
|
||||
val issuance: InstitutionReference,
|
||||
@ -45,10 +47,10 @@ object ComedyPaper : Contract {
|
||||
with(tx) {
|
||||
// There are two possible things that can be done with CP. The first is trading it. The second is redeeming it
|
||||
// for cash on or after the maturity date.
|
||||
val command = args.requireSingleCommand<ComedyPaper.Commands>()
|
||||
val command = args.requireSingleCommand<CommercialPaper.Commands>()
|
||||
|
||||
// For now do not allow multiple pieces of CP to trade in a single transaction. Study this more!
|
||||
val input = inStates.filterIsInstance<ComedyPaper.State>().single()
|
||||
val input = inStates.filterIsInstance<CommercialPaper.State>().single()
|
||||
|
||||
requireThat {
|
||||
"the transaction is signed by the owner of the CP" by (command.signers.contains(input.owner))
|
||||
@ -56,7 +58,7 @@ object ComedyPaper : Contract {
|
||||
|
||||
when (command.value) {
|
||||
is Commands.Move -> requireThat {
|
||||
val output = outStates.filterIsInstance<ComedyPaper.State>().single()
|
||||
val output = outStates.filterIsInstance<CommercialPaper.State>().single()
|
||||
"the output state is the same as the input state except for owner" by (input.withoutOwner() == output.withoutOwner())
|
||||
}
|
||||
|
||||
@ -65,7 +67,7 @@ object ComedyPaper : Contract {
|
||||
// Do we need to check the signature of the issuer here too?
|
||||
"the paper must have matured" by (input.maturityDate < time)
|
||||
"the received amount equals the face value" by (received == input.faceValue)
|
||||
"the paper must be destroyed" by outStates.filterIsInstance<ComedyPaper.State>().none()
|
||||
"the paper must be destroyed" by outStates.filterIsInstance<CommercialPaper.State>().none()
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,7 @@ val TEST_TX_TIME = Instant.parse("2015-04-17T12:00:00.00Z")
|
||||
// a sandbox. For now we just instantiate right at the start of the program.
|
||||
val TEST_PROGRAM_MAP: Map<SecureHash, Contract> = mapOf(
|
||||
CASH_PROGRAM_ID to Cash,
|
||||
CP_PROGRAM_ID to ComedyPaper,
|
||||
CP_PROGRAM_ID to CommercialPaper,
|
||||
DUMMY_PROGRAM_ID to DummyContract
|
||||
)
|
||||
|
||||
|
@ -7,7 +7,7 @@ import com.esotericsoftware.kryo.io.Input
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
import com.esotericsoftware.kryo.serializers.JavaSerializer
|
||||
import contracts.Cash
|
||||
import contracts.ComedyPaper
|
||||
import contracts.CommercialPaper
|
||||
import core.*
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
@ -223,9 +223,9 @@ fun createKryo(): Kryo {
|
||||
registerDataClass<Cash.State>()
|
||||
register(Cash.Commands.Move.javaClass)
|
||||
registerDataClass<Cash.Commands.Exit>()
|
||||
registerDataClass<ComedyPaper.State>()
|
||||
register(ComedyPaper.Commands.Move.javaClass)
|
||||
register(ComedyPaper.Commands.Redeem.javaClass)
|
||||
registerDataClass<CommercialPaper.State>()
|
||||
register(CommercialPaper.Commands.Move.javaClass)
|
||||
register(CommercialPaper.Commands.Redeem.javaClass)
|
||||
|
||||
// And for unit testing ...
|
||||
registerDataClass<DummyPublicKey>()
|
||||
|
@ -5,8 +5,8 @@ import org.junit.Test
|
||||
|
||||
// TODO: Finish this off.
|
||||
|
||||
class ComedyPaperTests {
|
||||
val PAPER_1 = ComedyPaper.State(
|
||||
class CommercialPaperTests {
|
||||
val PAPER_1 = CommercialPaper.State(
|
||||
issuance = InstitutionReference(MEGA_CORP, OpaqueBytes.of(123)),
|
||||
owner = DUMMY_PUBKEY_1,
|
||||
faceValue = 1000.DOLLARS,
|
||||
@ -30,15 +30,15 @@ class ComedyPaperTests {
|
||||
this.rejects()
|
||||
|
||||
transaction {
|
||||
arg(DUMMY_PUBKEY_2) { ComedyPaper.Commands.Move }
|
||||
arg(DUMMY_PUBKEY_2) { CommercialPaper.Commands.Move }
|
||||
this `fails requirement` "is signed by the owner"
|
||||
}
|
||||
|
||||
arg(DUMMY_PUBKEY_1) { ComedyPaper.Commands.Move }
|
||||
arg(DUMMY_PUBKEY_1) { CommercialPaper.Commands.Move }
|
||||
arg(DUMMY_PUBKEY_1) { Cash.Commands.Move }
|
||||
this.accepts()
|
||||
}.chain("a") {
|
||||
arg(DUMMY_PUBKEY_2, MINI_CORP_KEY) { ComedyPaper.Commands.Redeem }
|
||||
arg(DUMMY_PUBKEY_2, MINI_CORP_KEY) { CommercialPaper.Commands.Redeem }
|
||||
|
||||
// No cash output, can't redeem like that!
|
||||
this.rejects("no cash being redeemed")
|
Loading…
x
Reference in New Issue
Block a user