mirror of
https://github.com/corda/corda.git
synced 2024-12-19 13:08:04 +00:00
Add missing checks on settled amount
The obligation `Settle` command takes in an amount to be settled, but only uses the underlying token from it. This enforces that the settled amount matches the value seen moving.
This commit is contained in:
parent
44dee97899
commit
406196fb69
@ -182,14 +182,16 @@ class Obligation<P> : ClauseVerifier() {
|
||||
}
|
||||
}
|
||||
|
||||
// Insist that we can be the only contract consuming inputs, to ensure no other contract can think it's being
|
||||
// settled as well
|
||||
val totalAmountSettled = Amount(totalPenniesSettled, command.value.amount.token)
|
||||
requireThat {
|
||||
// Insist that we can be the only contract consuming inputs, to ensure no other contract can think it's being
|
||||
// settled as well
|
||||
"all move commands relate to this contract" by (moveCommands.map { it.value.contractHash }
|
||||
.all { it == null || it == Obligation<P>().legalContractReference })
|
||||
// Settle commands exclude all other commands, so we don't need to check for contracts moving at the same
|
||||
// time.
|
||||
"amounts paid must match recipients to settle" by inputs.map { it.owner }.containsAll(amountReceivedByOwner.keys)
|
||||
"amount in settle command ${command.value.amount} matches settled total ${totalAmountSettled}" by (command.value.amount == totalAmountSettled)
|
||||
"signatures are present from all obligors" by command.signers.containsAll(requiredSigners)
|
||||
"there are no zero sized inputs" by inputs.none { it.amount.quantity == 0L }
|
||||
"at obligor ${obligor.name} the obligations after settlement balance" by
|
||||
|
@ -462,9 +462,9 @@ class ObligationTests {
|
||||
transaction("Settlement") {
|
||||
input(oneMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY))
|
||||
input(500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` ALICE_PUBKEY)
|
||||
output("Alice's $5,000,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) }
|
||||
output("Alice's $500,000 obligation to Bob") { halfAMillionDollars.OBLIGATION between Pair(ALICE, BOB_PUBKEY) }
|
||||
output("Bob's $500,000") { 500000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle<Currency>(Amount(oneMillionDollars.quantity, inState.issuanceDef)) }
|
||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle<Currency>(Amount(oneMillionDollars.quantity / 2, inState.issuanceDef)) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
||||
this.verifies()
|
||||
}
|
||||
@ -482,6 +482,19 @@ class ObligationTests {
|
||||
this `fails with` "all inputs are in the normal state"
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure settlement amount must match the amount leaving the ledger
|
||||
ledger {
|
||||
obligationTestRoots(this)
|
||||
transaction("Settlement") {
|
||||
input("Alice's $1,000,000 obligation to Bob")
|
||||
input("Alice's $1,000,000")
|
||||
output("Bob's $1,000,000") { 1000000.DOLLARS.CASH `issued by` defaultIssuer `owned by` BOB_PUBKEY }
|
||||
command(ALICE_PUBKEY) { Obligation.Commands.Settle<Currency>(Amount(oneMillionDollars.quantity / 2, inState.issuanceDef)) }
|
||||
command(ALICE_PUBKEY) { Cash.Commands.Move(Obligation<Currency>().legalContractReference) }
|
||||
this `fails with` "amount in settle command"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user