from lender wallet to contract to some intermediate Lender account
Exactly. Marlowe uses an account model within the contract. You can think of Marlowe as having internal accounts for the participants in the contract, in order to keep track of who owns which funds.
- This is important because if a contract closes (via the
Close block in Blockly) with funds left in the internal accounts, then the contract will pay each account holder their funds. (This means that it is impossible to write a Marlowe contract that loses funds forever because it forgets to pay them.) You can experiment with this in Playground by depositing to an account, but not explicitly paying out of that account; when
Close is executed, the payment is made for that account even though there wasn’t a
--from-party indicates that the funds are coming from the external wallet with
$LENDER_ADDR. For security, the Marlowe deposit must be signed by the key for
$LENDER_ADDR. (If role tokens were used, then the deposit would have to be authorized by the holder of the role token for this party.)
--to-party indicates that those funds are being stored in the internal account for
$LENDER_ADDR within the Marlowe contract.
You can see how the internal accounts change in Marlowe Playground by clicking on the
Current State tab when you simulate:
You can also use https://marlowescan.com/ to view the state in each Marlowe transaction that has occurred on any of the public Cardano networks:
Can’t we just say that Lender transfers money to contract wallet once and all subsequent transactions are happening from contract wallet.
Although on the blockchain the contract’s UTxO holds the funds, for the aforementioned security reasons Marlowe requires that they be tagged a belonging to one or more internal accounts.
With this no need for having Lender or Borrower key in the contract.
You certainly could design a contract that doesn’t hold funds in an account for the Lender or Borrower key. For example, the Escrow contract could deposit funds in an internal account called “Contract” (or “Funds” or whatever). The initial deposit would be
--to-party Contract, and payments could be made from the “Contract” role. However, you might find that changing the Escrow contract in this way is a little tricky because you need to make sure that the logic is correct for either the Seller to be paid or the Buyer to be refunded (depending on scenario), regardless of situations where one of the parties fails to act (which causes a timeout).
Could you please explain, I am little lost here or missing something fundamental.
If you use roles in the contract (which means that role tokens are used for the authorizations instead of keys for addresses), then the contract never needs to refer to any addresses.
Basically, I want to avoid saving any wallet private key.
In the end, every transaction must be signed by some private key. The way to avoid ever storing or handling those signing keys yourself is to connect your contract to a CIP-30 wallet (typically a web browser extension). Then the wallet securely manages the user’s signing keys.