Reference: Choices

This page gives reference information on choices. For information on the high-level structure of a choice, see Overview: Template Structure.

choice First or controller First

There are two ways you can start a choice:

  • start with the choice keyword
  • start with the controller keyword

Warning

controller first syntax is deprecated since Daml 2.0 and will be removed in a future version. For more information, see Deprecation of controller first syntax.

    -- option 1 for specifying choices: choice name first
    choice NameOfChoice
      : () -- replace () with the actual return type
      with
        party : Party -- parameters here
      controller party
      do
        return () -- replace this line with the choice body

    -- option 2 for specifying choices (deprecated syntax): controller first
    controller exampleParty can
      NameOfAnotherChoice
        : () -- replace () with the actual return type
        with
          party : Party -- parameters here
        do
          return () -- replace the line with the choice body

The main difference is that starting with choice means that you can pass in a Party to use as a controller. If you do this, you must make sure that you add that party as an observer, otherwise they won’t be able to see the contract (and therefore won’t be able to exercise the choice).

In contrast, if you start with controller, the controller is automatically added as an observer when you compile your Daml files.

A secondary difference is that starting with choice allows choice observers to be attached to the choice using the observer keyword. The choice observers are a list of parties that, in addition to the stakeholders, will see all consequences of the action.

    -- choice observers may be specified if option 1 is used
    choice NameOfChoiceWithObserver
      : () -- replace () with the actual return type
      with
        party : Party -- parameters here
      observer party -- optional specification of choice observers (only available in Daml-LF >=1.11)
      controller exampleParty
      do
        return () -- replace this line with the choice body

Choice Name

Option 1 for specifying choices: choice name first
    choice ExampleChoice1
      : () -- replace () with the actual return type
Option 2 for specifying choices (deprecated syntax): controller first
      ExampleChoice2
        : () -- replace () with the actual return type
  • The name of the choice. Must begin with a capital letter.
  • If you’re using choice-first, preface with choice. Otherwise, this isn’t needed.
  • Must be unique in your project. Choices in different templates can’t have the same name.
  • If you’re using controller-first, you can have multiple choices after one can, for tidiness. However, note that this syntax is deprecated and will be removed in a future version of Daml.

Controllers

Option 1 for specifying choices: choice name first
      controller exampleParty
Option 2 for specifying choices (deprecated syntax): controller first
    controller exampleParty can
  • controller keyword

  • The controller is a comma-separated list of values, where each value is either a party or a collection of parties.

    The conjunction of all the parties are required to authorize when this choice is exercised.

Contract Consumption

If no qualifier is present, choices are consuming: the contract is archived before the evaluation of the choice body and both the controllers and all contract stakeholders see all consequences of the action.

Preconsuming Choices

Option 1 for specifying choices: choice name first
    preconsuming choice ExampleChoice5
      : () -- replace () with the actual return type
Option 2 for specifying choices (deprecated syntax): controller first
      preconsuming ExampleChoice7
        : () -- replace () with the actual return type
  • preconsuming keyword. Optional.
  • Makes a choice pre-consuming: the contract is archived before the body of the exercise is executed.
  • The create arguments of the contract can still be used in the body of the exercise, but cannot be fetched by its contract id.
  • The archival behavior is analogous to the consuming default behavior.
  • Only the controllers and signatories of the contract see all consequences of the action. Other stakeholders merely see an archive action.
  • Can be thought as a non-consuming choice that implicitly archives the contract before anything else happens

Postconsuming Choices

Option 1 for specifying choices: choice name first
    postconsuming choice ExampleChoice6
      : () -- replace () with the actual return type
Option 2 for specifying choices (deprecated syntax): controller first
      postconsuming ExampleChoice8
        : () -- replace () with the actual return type
  • postconsuming keyword. Optional.
  • Makes a choice post-consuming: the contract is archived after the body of the exercise is executed.
  • The create arguments of the contract can still be used in the body of the exercise as well as the contract id for fetching it.
  • Only the controllers and signatories of the contract see all consequences of the action. Other stakeholders merely see an archive action.
  • Can be thought as a non-consuming choice that implicitly archives the contract after the choice has been exercised

Non-consuming Choices

Option 1 for specifying choices: choice name first
    nonconsuming choice ExampleChoice3
      : () -- replace () with the actual return type
Option 2 for specifying choices (deprecated syntax): controller first
      nonconsuming ExampleChoice4
        : () -- replace () with the actual return type
  • nonconsuming keyword. Optional.
  • Makes a choice non-consuming: that is, exercising the choice does not archive the contract.
  • Only the controllers and signatories of the contract see all consequences of the action.
  • Useful in the many situations when you want to be able to exercise a choice more than once.

Return Type

  • Return type is written immediately after choice name.
  • All choices have a return type. A contract returning nothing should be marked as returning a “unit”, ie ().
  • If a contract is/contracts are created in the choice body, usually you would return the contract ID(s) (which have the type ContractId <name of template>). This is returned when the choice is exercised, and can be used in a variety of ways.

Choice Arguments

      with
        exampleParameter : Text

Choice Body

  • Introduced with do
  • The logic in this section is what is executed when the choice gets exercised.
  • The choice body contains Update expressions. For detail on this, see Reference: Updates.
  • By default, the last expression in the choice is returned. You can return multiple updates in tuple form or in a custom data type. To return something that isn’t of type Update, use the return keyword.

Deprecation of controller first syntax

Since Daml 2.0, using controller first syntax to define a choice will result in the following warning:

The syntax 'controller ... can' is deprecated,
it will be removed in a future version of Daml.
Instead, use 'choice ... with ... controller' syntax.
Note that 'choice ... with ... controller' syntax does not
implicitly add the controller as an observer,
so it must be added explicitly as one (or as a signatory).

Migrating

Users are strongly encouraged to adapt their choices to use choice first syntax. This is a schema to adapt affected code:

  1. For each controller ... can block,
    1. Note the parties between the controller and can keywords; these are the block controllers.
    2. Ensure that all the block controllers are signatories or observers of the template. If any controller is neither a signatory nor observer of the template, add it as an observer.
    3. For each choice in the block,
      1. Prefix the choice name with the choice keyword, but keep any consumption qualifiers before choice.
      2. Add a controller clause with the block controllers before the body of the choice (the do block) .
    4. Remove the controller ... can block header and adjust indentation as necessary.

Turning off the warning

This warning is controlled by the warning flag controller-can, which means that it can be toggled independently of other warnings. This is especially useful for gradually migrating code that used this syntax.

To turn off the warning within a Daml file, add the following line at the top of the file:

{-# OPTIONS_GHC -Wno-controller-can #-}

To turn it off for an entire Daml project, add the following entry to the build-options field of the project’s daml.yaml file

build-options:
- --ghc-option=-Wno-controller-can

Within a project where the warning has been turned off via the daml.yaml file, it can be turned back on for individual Daml files by adding the following line at the top of each file:

{-# OPTIONS_GHC -Wcontroller-can #-}