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.
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
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.