DAML Script not working

Hi, this DAML Script is not working. Can please take a look to fix it for daml version 2, what is the problem with it.
setup : Script ()
setup = script do
bank ← allocateParty “AIB Bank”
martin ← allocateParty “Alice”
carshop ← allocateParty “CarShop”
let
cash = Cash
with
issuer = bank
owner = alice
currency = CHF
amount = 2000.0
cashCid ← submit bank do
createCmd cash
let
bikeRepair = CarRepair with
carShop = carshop
carOwner = alice
description = “car repair and maintainance”
price = 200.0
paymentDue = date 27 Jun 2022
proposalCid ← submit shop do
createCmd CarRepairProposal
with
proposer = carshop
receiver = alice
proposal = CarRepair
repairCid ← submit alice do
exerciseCmd proposalCid Accept
submit alice do
exerciseCmd repairCid Pay with cashCid

Please encode your code in a markdown code block to make it easier to read:

```
yourcodehere
```

It would also be great if you could share the error you’re receiving.

1 Like

Blockquote

setup : Script ()
setup = script do
bank ← allocateParty “AIB Bank”
martin ← allocateParty “Alice”
carshop ← allocateParty “CarShop”
let
cash = Cash
with
issuer = bank
owner = alice
currency = CHF
amount = 2000.0
cashCid ← submit bank do
createCmd cash
let
bikeRepair = CarRepair with
carShop = carshop
carOwner = alice
description = “car repair and maintainance”
price = 200.0
paymentDue = date 27 Jun 2022
proposalCid ← submit shop do
createCmd CarRepairProposal
with
proposer = carshop
receiver = alice
proposal = CarRepair
repairCid ← submit alice do
exerciseCmd proposalCid Accept
submit alice do
exerciseCmd repairCid Pay with cashCid


Capture2

Blockquote

@Iqra_Mustafa1
I assume you wanted the whole code snippet you provided to be part of the function named “setup”, which returns Script (). If this is the case, the parsing error is due to missing indentation. In this case the whole body of the function falls within the “do” block and should be indented.
As I attempted to fix your code I found a bunch of other errors, like incorrect date format etc. The setup function below is free from syntax errors and works for me after creating a skeleton for the templates utilized in this function. I can’t be certain it will work for you, as your templates must be different from mine. But it should bring you closer to the working Daml Script.

setup : Script ()
setup = script do
  bank <- allocateParty "AIB Bank"
  alice <- allocateParty "Alice"
  carshop <- allocateParty "CarShop"
  let
    cash = Cash with
      issuer = bank
      owner = alice
      currency = "CHF"
      amount = 2000.0
  cashCid <- submit bank do
    createCmd cash
  let
    carRepair = CarRepair with
      carShop = carshop
      carOwner = alice
      description = "car repair and maintainance"
      price = 200.0
      paymentDue = date 2022 Jun 27
  proposalCid <- submit carshop do
    createCmd CarRepairProposal
      with
        proposer = carshop
        receiver = alice
        proposal = carRepair
  repairCid <- submit alice do
          exerciseCmd proposalCid Accept
  submit alice do
      exerciseCmd repairCid Pay with cashCid
  return ()

This is the DAML Contract. I have checked the DAML Script but still its giving error on Script().Error/ServiceCenter.daml:58:7: error:
Not in scope: type constructor or class ‘Script’typecheck

Blockquote
module ServiceCenter where

data Currency = USD | EUR | GBP
deriving (Eq, Show)
template Cash
with
issuer: Party
owner: Party
currency: Currency
amount: Decimal
where
signatory issuer
observer owner

nonconsuming choice Transfer : ContractId Cash
    with
      newOwner: Party
    controller owner
    do
      archive self
      create this with owner=newOwner

template CarRepair
with
carShop: Party
carOwner: Party
description: Text
price: Decimal
paymentDue: Date
where
signatory carShop
observer carOwner

nonconsuming choice  Pay : ContractId Cash
    with
      cashCid: ContractId Cash
    controller carOwner
    do
      cash <- fetch cashCid
      assert (
        cash.currency == USD && 
        cash.amount == price)
      exercise cashCid Transfer with newOwner=carShop

template CarRepairProposal
with
proposer: Party
receiver: Party
proposal: CarRepair
where
signatory proposer
observer receiver

nonconsuming choice  Accept : ContractId CarRepair
   controller receiver
    do
      create proposal

Blockquote

@Iqra_Mustafa1
With these templates, replacing currency = "CHF" with say currency = USD when creating the cash record would resolve the compile error. But the script would still fail because of the mismatch in the amount of the Cash contract and the value of the price field in CarRepair contract, and because of the assertion that checks that these two values must match in the Pay choice of the CarRepair template.
Here’s the Daml Script code that works with the templates you provided.

setup : Script ()
setup = script 
  do
  bank <- allocateParty "AIB Bank"
  alice <- allocateParty "Alice"
  carshop <- allocateParty "CarShop"
  let
    cash = Cash with
      issuer = bank
      owner = alice
      currency = USD
      amount = 200.0
  cashCid <- submit bank do
    createCmd cash
  let
    carRepair = CarRepair with
      carShop = carshop
      carOwner = alice
      description = "car repair and maintainance"
      price = 200.0
      paymentDue = date 2022 Jun 27
  proposalCid <- submit carshop do
    createCmd CarRepairProposal
      with
        proposer = carshop
        receiver = alice
        proposal = carRepair
  repairCid <- submit alice do
          exerciseCmd proposalCid Accept
  submit alice do
      exerciseCmd repairCid Pay with cashCid
  return ()

I was making some changes in the contract in the CarRepair Choice PAY:

nonconsuming choice  Pay : ContractId Cash
        with
          cashCid: ContractId Cash
          cash: Cash
     controller carOwner
     do
     assert (cash.currency == USD && cash.amount == price)
     exercise cashCid Transfer with newOwner = carShop

In this case, in the above code I replaced the fetchID statement after do (Please see correct contract code above in this thread(carRepair Template)). And added cash = Cash. When I tested that by making changes then I observe following behaviour on DAML HUB

The green box represents the output of correct model which is above in this thread, which is asking for only contractID Cash to process the payment. However, the red box depicts the output of this amended approach. Actually when I try to access the Cash template arguments in carRepair choice PAY, it is asking again to enter all arguments of cash template to process cash transfer into carRepair.

I wanted to ask by doing cash = Cash is also right , and removing fetchID after do is ok. Because the contract is working fine. However, this approach again loaded the cash template. This approach can lead a logical vulnerability. any thoughts on this???

@Iqra_Mustafa1
Your latest implementation of the Pay choice introduces a logical error. In Daml the contract ID and the contract payload are not interchangeable.
The field cash that you introduced in the Pay choice has no relation to the field cashCid. The values in these two fields can represent two completely different contracts. Moreover, the value of the cash field can be a Daml record of type Cash, which does not exist on the ledger at all.
Let me illustrate. Suppose the contract ID you pass to the cashCid field refers to a Cash contract representing 20 EUR. Then, according to the business logic you’re looking to implement, the exercise of the Pay choice should fail because the currency and the amount of the Cash contract does not match the currency and the price of the CarRepair contract, right? Well, with your latest implementation of the Pay choice, I can pass a Cash contract representing 20 EUR to the cashCid field. And I can pass to the cash field of the Pay choice a Daml record of type Cash, which does not exist on the ledger, and which has the currency and the amount field values that match the currency and the price in the CarRepair contract, so the transaction will succeed. In the following Daml script the value of the dummyCashRecord variable is a Daml record, which does not exist on the ledger. By passing this variable to the Pay choice I successfully transfer 20 EUR Cash contract as payment for car repair that car repair shop wants 200 USD for.

setup : Script ()
setup = script 
  do
  bank <- allocateParty "AIB Bank"
  alice <- allocateParty "Alice"
  carshop <- allocateParty "CarShop"
  let
    cash = Cash with
      issuer = bank
      owner = alice
      currency = EUR
      amount = 20.0
  cashCid <- submit bank do
    createCmd cash
  let
    carRepair = CarRepair with
      carShop = carshop
      carOwner = alice
      description = "car repair and maintainance"
      price = 200.0
      paymentDue = date 2022 Jun 27
  proposalCid <- submit carshop do
    createCmd CarRepairProposal
      with
        proposer = carshop
        receiver = alice
        proposal = carRepair
  repairCid <- submit alice do
          exerciseCmd proposalCid Accept
  let 
    dummyCashRecord = Cash with
      issuer = bank
      owner = alice
      currency = USD
      amount = 200.0    
  submit alice do
      exerciseCmd repairCid Pay with 
        cashCid
        cash = dummyCashRecord  
  return ()

If you want to use a contract in a choice (e.g. archive the contract or exercise a choice on it), you need to pass the contract ID to the choice. And if you need to use the contract data in the choice, then you need to fetch the contract using contract ID.