0
votes

I would like to have a condition in a state contract that depends on an agreed rule between the parties involved. I don't want to hardcode this rule as the parties may want to agree to update the rule later. For example:

  //'y' is an agreed value between the participants.    
  if (inputThingState.amount > y) {
         "If thing amount is greater than y, then status must equal 1" using outputThingState.status == 1
   }

One way of doing this is to have a Rule State object, which is proposed and agreed by the relevant parties in a prior transaction. Then add the approved Rule state object as an input to the current transaction. Therefore the condition would look like this:

if (inputThingState.amount > inputRuleState.y) {
     "If thing amount is greater than y, then status must equal 1" using outputThingState.status == 1
}

This seems to work but it means that the RuleState object is consumed, so it must be copied and added as an output state, so that it is available to use again. It could also cause problems as multiple transactions might want to consume the same RuleState at the same time.

Is there a more elegant way of achieving this? (Possibly by passing in the approved rule as Command data.)

1

1 Answers

0
votes

One way to achieve this would be to place the rule in a command:

import net.corda.core.contracts.CommandData
import net.corda.core.contracts.Contract
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.requireThat
import net.corda.core.identity.Party
import net.corda.core.transactions.LedgerTransaction

class MyState(val amount: Int, override val participants: List<Party>): ContractState

class MyCommand(val amount: Int) : CommandData

class MyStateContract: Contract {
    override fun verify(tx: LedgerTransaction) {
        requireThat {
            "There is one input state" using (tx.inputsOfType<MyState>().size == 1)
            "There is one command" using (tx.commandsOfType<MyCommand>().size == 1)
            val myState = tx.inputsOfType<MyState>().single()
            val myCommand = tx.commandsOfType<MyCommand>().single()
            "The amount of the state and the command match" using (myState.amount == myCommand.value.amount)
        }
    }
}

Another would be to write the flow so that it refuses to sign any transaction where the condition is not satisfied. Just because a transaction is contractually valid, doesn't mean you're obliged to sign. You could update the flow whenever there's a change in the rules.