Multiple party agreement¶
The Multiple Party Agreement pattern uses a Pending contract as a wrapper for the Agreement contract. Any one of the signatory parties can kick off the workflow by creating a Pending contract on the ledger, filling in themselves in all the signatory fields. The Agreement contract is not created on the ledger until all parties have agreed to the Pending contract, and replaced the initiator’s signature with their own.
The Initiate and Accept shows how to create bilateral agreements in DAML. However, a project or a workflow often requires more than two parties to reach a consensus and put their signatures on a multi-party contract. For example, in a large construction project, there are at least three major stakeholders: Owner, Architect and Builder. All three parties need to establish agreement on key responsibilities and project success criteria before starting the construction.
If such an agreement were modeled as three separate bilateral agreements, no party could be sure if there are conflicts between their two contracts and the third contract between their partners. If the Initiate and Accept were used to collect three signatures on a multi-party agreement, unnecessary restrictions would be put on the order of consensus and a number of additional contract templates would be needed as the intermediate steps. Both solution are suboptimal.
Following the Multiple Party Agreement pattern, it is easy to write an agreement contract with multiple signatories and have each party accept explicitly.
- Agreement contract
The Agreement contract represents the final agreement among a group of stakeholders. Its content can vary per business case, but in this pattern, it always has multiple signatories.
template Agreement with signatories: [Party] where signatory signatories
- Pending contract
The Pending contract needs to contain the contents of the proposed Agreement contract, as a parameter. This is so that parties know what they are agreeing to, and also so that when all parties have signed, the Agreement contract can be created.
The Pending contract has a list of parties who have signed it, and a list of parties who have yet to sign it. If you add these lists together, it has to be the same set of parties as the
signatoriesof the Agreement contract.
All of the
toSignparties have the choice to
Sign. This choice checks that the party is indeed a member of
toSign, then creates a new instance of the Pending conract where they have been moved to the
template Pending with agree: Agreement signed: [Party] toSign: [Party] where signatory signed observer toSign choice Sign : ContractId Pending with signer : Party controller signer do assert (signer `elem` toSign) create this with signed = signer :: signed, toSign = delete signer toSign
Once all of the parties have signed, any of them can create the final Agreement contract using the
Finalizechoice. This checks that all of the signatories for the Agreement have signed the Pending contract.
choice Finalize : ContractId Agreement with signer : Party controller signer do assert (sort signed == sort agree.signatories) create agree
- Collecting the signatures in practice
Since the final Pending contract has multiple signatories, it cannot be created in that state by any one stakeholder.
However, a party can create a pending contract, with all of the other parties in the
parties@[person1, person2, person3, person4] <- makePartiesFrom ["Alice", "Bob", "Clare", "Dave"] let agree = Agreement with signatories = parties pending <- person1 `submit` do create Pending with agree; signed = [head parties]; toSign = tail parties
Once the Pending contract is created, the other parties can sign it. For simplicity, the example code only has choices to express consensus (but you might want to add choices to Accept, Reject, or Negotiate).
pending <- person2 `submit` do exercise pending Sign with signer = person2 pending <- person3 `submit` do exercise pending Sign with signer = person3 pending <- person4 `submit` do exercise pending Sign with signer = person4 pendingFailTest <- person3 `submitMustFail` do exercise pending Sign with signer = person4
Once all of the parties have signed the Pending contract, any of them can then exercise the
Finalizechoice. This creates the Agreement contract on the ledger.
person1 `submit` do exercise pending Finalize with signer = person1