Error “Argument is not of serializable type”¶
This error occurs when you’re using a function as a parameter to a template. For example, here is a contract that creates a
Payout controller by a receiver’s supervisor:
template SupervisedPayout with supervisor : Party -> Party receiver : Party giver : Party amount : Decimal where signatory giver observer (supervisor receiver) choice SupervisedPayout_Call : ContractId Payout controller supervisor receiver do create Payout with giver; receiver; amount
Hovering over the compilation error displays:
[Type checker] Argument expands to non-serializable type Party -> Party.
How to model an agreement with another party¶
To enter into an agreement, create a contract from a template that has explicit
You’ll need to use a series of contracts that give each party the chance to consent, via a contract choice.
Because of the rules that Daml enforces, it is not possible for a single party to create an instance of a multi-party agreement. This is because such a creation would force the other parties into that agreement, without giving them a choice to enter it or not.
How to model rights¶
Use a contract choice to model a right. A party exercises that right by exercising the choice.
How to void a contract¶
To allow voiding a contract, provide a choice that does not create any new contracts. Daml contracts are archived (but not deleted) when a consuming choice is made - so exercising the choice effectively voids the contract.
However, you should bear in mind who is allowed to void a contract, especially without the re-sought consent of the other signatories.
How to represent off-ledger parties¶
You’d need to do this if you can’t set up all parties as ledger participants, because the Daml
Party type gets associated with a cryptographic key and can so only be used with parties that have been set up accordingly.
To model off-ledger parties in Daml, they must be represented on-ledger by a participant who can sign on their behalf. You could represent them with an ordinary
This isn’t very private, so you could use a numeric ID/an accountId to identify the off-ledger client.
How to limit a choice by time¶
Some rights have a time limit: either a time by which it must be exercised or a time before which it cannot be exercised.
You can use
getTime to get the current time, and compare your desired time to it. Use
assert to abort the choice if your time condition is not met.
How to model a mandatory action¶
If you want to ensure that a party takes some action within a given time period. Might want to incur a penalty if they don’t - because that would breach the contract.
For example: an Invoice that must be paid by a certain date, with a penalty (could be something like an added interest charge or a penalty fee). To do this, you could have a time-limited Penalty choice that can only be exercised after the time period has expired.
However, note that the penalty action can only ever create another contract on the ledger, which represents an agreement between all parties that the initial contract has been breached. Ultimately, the recourse for any breach is legal action of some kind. What Daml provides is provable violation of the agreement.
When to use Optional¶
Optional type, from the standard library, to indicate that a value is optional, i.e, that in some cases it may be missing.
In functional languages,
Optional is a better way of indicating a missing value than using the more familiar value “NULL”, present in imperative languages like Java.
Optional.daml from the standard library:
Then, you can create
Optional values like this:
Some "Some text" -- Optional value exists.
None -- Optional value does not exist.
You can test for existence in various ways:
-- isSome returns True if there is a value. if isSome m then "Yes" else "No"
-- The inverse is isNone. if isNone m then "No" else "Yes"
If you need to extract the value, use the
It returns a value of a defined type, and takes a
Optional value and a function that can transform the value contained in a
Some value of the
Optional to that type. If it is missing
optional also takes a value of the return type (the default value), which will be returned if the
Optional value is
let f = \ (i : Int) -> "The number is " <> (show i) let t = optional "No number" f someValue
Some 5, the value of
t would be
"The number is 5". If it was
t would be
"No number". Note that with
optional, it is possible to return a different type from that contained in the
Optional value. This makes the
Optional type very flexible.
There are many other functions in “Optional.daml” that let you perform familiar functional operations on structures that contain
Optional values – such as
filter, etc. on
How to test that a contract is visible to a party¶
queryContractId: its first argument is a party, and the second is a
ContractId. If the contract corresponding to that
ContractId exists and is visible to the party, the result will be wrapped in
Some, otherwise the result will be
submit block and a
fetch operation. The
submit block tests that the contract (as a
ContractId) is visible to that party, and the
fetch tests that it is valid, i.e., that the contract does exist.
For example, if we wanted to test for the existence and visibility of an
Invoice, visible to ‘Alice’, whose ContractId is bound to invoiceCid, we could say:
Some result <- alice `queryContractId` invoiceCid
Note that we pattern match on the
Some constructor. If the contract doesn’t exist or is not visible to ‘Alice’, the test will fail with a pattern match error.
Now that the contract is bound to a variable, we can check whether it has some expected values:
result === Invoice with payee = alice payer = acme amount = 130.0 service = "A job well done" timeLimit = datetime 1970 Feb 20 0 0 0
How to test that an update action cannot be committed¶
submitMustFail function. This is similar in form to the
submit function, but is an assertion that an update will fail if attempted by some Party.