Managing contention by catching `CONTRACT_NOT_FOUND` errors

Consider the following model, where I can have multiple outstanding offers for an asset to be transferred.

template ProposeAsset
  with
    assetId   : ContractId Asset
    owner     : Party
    recipient : Party
  where
    signatory owner
    observer recipient
    choice Accept : ContractId AcceptAsset
      controller recipient
      do create AcceptAsset with assetId, currentOwner = owner, newOwner = recipient

template AcceptAsset
  with
    assetId      : ContractId Asset
    currentOwner : Party
    newOwner     : Party
  where
    signatory newOwner
    observer currentOwner
    choice Finalize : ContractId Asset
      controller currentOwner
      do
        archive assetId
        create Asset with owner = newOwner

template Asset
  with
    owner : Party
  where
    signatory owner
    nonconsuming choice Propose : ContractId ProposeAsset
      with
        recipient : Party
      controller owner
      do create ProposeAsset with
          assetId = self
          owner = owner
          recipient = recipient

This model is prone to contention, as shown in the following test script, which “successfully fails”:

testAssetCannotBeGivenTwice : Script ()
testAssetCannotBeGivenTwice = script do
-- user_setup_begin
  alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
  bob <- allocatePartyWithHint "Bob" (PartyIdHint "Bob")
  charlie <- allocatePartyWithHint "Charlie" (PartyIdHint "Charlie")
  aliceId <- validateUserId "alice"
  bobId <- validateUserId "bob"
  charlieId <- validateUserId "charlie"
  createUser (User aliceId (Some alice)) [CanActAs alice]
  createUser (User bobId (Some bob)) [CanActAs bob]
  createUser (User charlieId (Some charlie)) [CanActAs charlie]
-- user_setup_end

  asset <- submit alice do
    createCmd Asset with
      owner = alice

  offerToBob <- submit alice do
    exerciseCmd asset Propose with recipient = bob
  bobAccepts <- submit bob do exerciseCmd offerToBob Accept

  offerToCharlie <- submit alice do
    exerciseCmd asset Propose with recipient = charlie
  charlieAccepts <- submit charlie do exerciseCmd offerToCharlie Accept

  submit alice do exerciseCmd bobAccepts Finalize
  submitMustFail alice do exerciseCmd charlieAccepts Finalize

Ideally, I would like to handle contention-related issues explicitly in my model.

For this reason, I would like to catch CONTRACT_NOT_FOUND errors and return an Optional ContractId Asset. Is that possible?

1 Like

You cannot catch contention errors within Daml. Daml exceptions are resolved during submission. However, contention errors usually only fail during validation. At that point, interpretation is already fixed and the transaction can only get accepted or rejected. To support handling that it would instead need to get reinterpreted in some form.

2 Likes