Consider
template Asset with
issuer : Party
owner : Party
name : Text
where
signatory issuer
observer owner
choice Transfer : ContractId TransferedAsset
with
newOwner : Party
controller owner
-- need both in order to succeed
-- controller owner, newOwner
do
create TransferedAsset with
owner = newOwner
previousOwner = owner
..
template TransferedAsset with
owner : Party
previousOwner : Party
name : Text
where
signatory owner, previousOwner
setup : Script ()
setup = do
alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
bob <- allocatePartyWithHint "Bob" (PartyIdHint "Bob")
aliceTV <- submit alice do
createCmd Asset with
issuer = alice
owner = alice
name = "TV"
bobTV <- submitMulti [alice, bob] [] do
exerciseCmd aliceTV Transfer with
newOwner = bob
pure ()
I was playing around with some transfer logic and out of laziness used a submitMulti
to avoid writing a propose & accept, but to my surprise I needed to add explicit authorization for both parties by adding the second non-signatory to the controller field. Does being a controller
explicitly narrow authorization within the choice
body?
According to Daml Authorization Rules,
In a Daml ledger, a party can authorize a subaction of a commit in either of the following ways:
- Every top-level action of the commit is authorized by all requesters of the commit.
- Every consequence of an exercise action act on a contract c is authorized by all signatories of c and all actors of act.
The way I read this is that the requesters of the commit containing an exercise
action do not authorize consequences of this exercise. Applying this to your example, Bob, who authorizes the exercise of the Transfer choice on aliceTV through submitMulti, does not authorize the creation of TransferAsset contract as a consequence of exercising the Transfer choice on aliceTV. To obtain Bob’s authorization for the consequences of the Transfer choice Bob must be either a signatory on the Asset contract or a controller on the Transfer choice.
Don’t we have bob
’s authorization when we:
submitMulti [alice, bob] [] do ...
The definition of act_as
under Commands says
Set of parties on whose behalf the command should be executed. If ledger API authorization is enabled, then the authorization metadata must authorize the sender of the request to act on behalf of each of the given parties. This field supersedes the party
field. The effective set of parties on whose behalf the command should be executed is the union of all parties listed in party
and act_as
, which must be non-empty. Each element must be a valid PartyIdString (as described in value.proto
). Optional
I expected us to act under the authorization of alice
and bob
.
The way I read the documentation, we do have both Alice’s and Bob’s authorization for the top level action (the exercise of Transfer choice). But not for the consequences of this action (the creation of TransferedAsset contract). For the latter we only have authorization from the signatories of the Asset contract and the controllers of the Transfer choice.
1 Like