G-d willing
I am trying to do something similar to the delegations pattern which is explained here: (The Delegation Pattern — Daml SDK 2.6.4 documentation).
I have the 2 following templates:
template Product
with
id: Text
owner: Party
responsible: Party
where
signatory owner, responsible
choice ChangeResponsible : ContractId Product
with
newRespobsible : Party
controller responsible
do
create this with responsible = newRespobsible
template RentAgreement
with
lessor: Party
lessee: Party
product: ContractId Product
where
signatory lessor, lessee
choice ChangeResponsibility : ContractId Product
controller lessor
do
exercise product ChangeResponsible with newRespobsible = lessee
Let’s create a script where Alice wants to rent a pen to Bob,
setup : Script ()
setup = script do
alice <- allocateParty "alice"
bob <- allocateParty "bob"
pen <- submit alice do
createCmd Product with owner = alice, responsible = alice, id ="1"
agreementId <- submitMulti [alice, bob] [] do
createCmd RentAgreement with
lessor = alice
lessee = bob
product = pen
submit alice do
exerciseCmd agreementId ChangeResponsibility
pure ()
This fails on authorization saying:
Script execution failed on commit at C1L2:63:3:
2: create of C1L2:Product at DA.Internal.Prelude:379:26
failed due to a missing authorization from 'bob'
Bob is a signatory on the rent agreement, so why when exercising the choice it says that it is missing?
Can I resolve it without adding another contract in the middle?
The authority of a contract signatory that’s available in a choice on a contract does not propagate to the consequences of the choice. In your example Bob’s authority is available in the ChangeResponsibility
choice on the RentAgreement
contract. But it does not propagate to the ChangeResponsible
choice on the Product
contract that is called from the ChangeResponsibility
choice. In the ChangeResponsible
choice on the Product
contract you only have the authority of the signatories of the Product
contract and of the controller of the ChangeResponsible
choice.
Instead of calling ChangeResponsible
choice on the Product
contract, in ChangeResponsibility
choice on the RentAgreement
contract you could fetch the Product
contract, archive it and create a new one with updated value for the responsible
field.
template Product
with
id: Text
owner: Party
responsible: Party
where
signatory owner, responsible
template RentAgreement
with
lessor: Party
lessee: Party
productId: ContractId Product
where
signatory lessor, lessee
choice ChangeResponsibility : ContractId Product
controller lessor
do
product <- fetch productId
archive productId
create product with responsible = lessee
testRent = script do
alice <- allocateParty "alice"
bob <- allocateParty "bob"
pen <- submit alice do
createCmd Product with owner = alice, responsible = alice, id ="1"
agreementId <- submitMulti [alice, bob] [] do
createCmd RentAgreement with
lessor = alice
lessee = bob
productId = pen
submit alice do
exerciseCmd agreementId ChangeResponsibility
pure ()
1 Like
Thank you @a_putkov for your response.
Is there a way to do it without archiving and re-creating the Product contract?
@cohen.avraham
I’m not sure I understand the question. The workflow in your original example archives the Product contract (by exercising a consuming choice on it) and recreates the contract with a new value for the field named responsible
. The example that I provided is no different in this sense.
Is there a way to do it without archiving and re-creating the Product contract?
To answer this question I need to understand what you’re looking to achieve here. In other words what specifically the word “it” in the question refers to.
Assuming what you’re looking to do is to mutate the state of a Product contract, there’s no way to achieve it without archiving and recreating the Product contract.
Daml contracts are immutable. The only way to simulate mutated state is to archive an existing contract and create another one in its stead with updated values for some fields.
@a_putkov, by it I mean to be able to change the responsible
of the product using a choice inside the Product
template.
And in the meantime, during my experiments, I succeeded to do it by adding the newRespobsible
party as an additional controller to the ChangeResponsible
choice.