Modify the state

In Corda, shared facts on the blockchain are represented as states. Your first task is to define a new state type to represent an IOU.

The ContractState interface

A Corda state is any instance of a class that implements the ContractState interface.

For your CorDapp, use the following ContractState interface:

interface ContractState {
    // The list of entities considered to have a stake in this state.
    val participants: List<AbstractParty>
  }
  ```
  

As you can see, the ContractState interface has a single field - participants. The participants field is a list of the entities for which this state is relevant.

Beyond this, your state is free to define any fields, methods, helpers or inner classes that the state requires to accurately represent a given type of shared fact on the blockchain.

Define IOUState

How should you define the IOUState representing IOUs on the blockchain? Beyond implementing the ContractState interface, your IOUState also needs properties to track the relevant features of the IOU:

  • The value of the IOU.
  • The lender of the IOU.
  • The borrower of the IOU.

There are many more fields you could include, such as the IOU’s currency, but let’s ignore those for now. Adding them later is often as simple as adding an additional property to your class definition.

  1. Open the file for for your language:

    • Java: Open TemplateState.java from contracts/src/main/java/com/template/states/TemplateState.java.
    • Kotlin: Open TemplateState.kt from contracts/src/main/kotlin/com/template/states/TemplateState.kt.
  2. Rename the TemplateState class to IOUState.

  3. Define IOUState by making the following changes:

    a. Add properties for value, lender and borrower, along with the required getters and setters in Java:

    • value is of type int (in Java)/Int (in Kotlin).
    • lender and borrower are of type Party.
      • Party is a built-in Corda type that represents an entity on the network.

    b. Override participants to return a list that shows the lender and borrower.

    • participants is a list of all the parties who should be notified of the creation or consumption of this state.

The IOUs that you issue onto a ledger will simply be instances of this class.

Outcome

Take a look at this code snippet. This is how your IOU state template should look after you have completed all the steps described above.

// Add this import:
import net.corda.core.identity.Party

// Replace TemplateState's definition with:
@BelongsToContract(TemplateContract::class)
class IOUState(val value: Int,
               val lender: Party,
               val borrower: Party) : ContractState {
    override val participants get() = listOf(lender, borrower)

}

// Add this import:
import net.corda.core.identity.Party;

// Replace TemplateState's definition with:
public class IOUState implements ContractState {
    private final int value;
    private final Party lender;
    private final Party borrower;

    public IOUState(int value, Party lender, Party borrower) {
        this.value = value;
        this.lender = lender;
        this.borrower = borrower;
    }

    public int getValue() {
        return value;
    }

    public Party getLender() {
        return lender;
    }

    public Party getBorrower() {
        return borrower;
    }

    @Override
    public List<AbstractParty> getParticipants() {
        return Arrays.asList(lender, borrower);
    }
}

Progress so far

You’ve defined an IOUState that can be used to represent IOUs as shared facts on a ledger. As you’ve seen, states in Corda are simply classes that implement the ContractState interface. They can have any additional properties and methods you like.

All that’s left to do is write the IOUFlow that will allow a node to orchestrate the creation of a new IOUState on the blockchain, while only sharing information on a need-to-know basis.

What about the contract?

If you’ve read the white paper or the key concepts section, you’ll know that each state has an associated contract that imposes invariants on how the state evolves over time. Including a contract isn’t crucial for our first CorDapp, so you’ll just use the empty TemplateContract and TemplateContract.Commands.Action command defined by the template for now.

/* We can use the requireSingleCommand function to extract command data from transaction.
 * However, it is possible to have multiple commands in a signle transaction.*/
final CommandWithParties<Commands> command = requireSingleCommand(tx.getCommands(), Commands.class);
final Commands commandData = command.getValue();

if (commandData.equals(new Commands.Send())) {
    //Retrieve the output state of the transaction
    IOUState output = tx.outputsOfType(IOUState.class).get(0);

    //Using Corda DSL function requireThat to replicate conditions-checks
    requireThat(require -> {
        require.using("No inputs should be consumed when sending the Hello-World message.", tx.getInputStates().size() == 0);
        require.using("The message must be Hello-World", output.getValue().equals("Hello-World"));
        return null;
    });
}

In the next tutorial, you’ll implement your own contract and command.

Was this page helpful?

Thanks for your feedback!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.

We're sorry this page wasn't helpful. Let us know how we can make it better!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Create an issue

Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.