Holding Upgrade¶
This tutorial demonstrates how a custodian can upgrade their holding implementation for the Transferable holding standard to a custom, extended version in a lazy manner. Specifically, the upgrade occurs seamlessly during a client’s transfer action.
We are going to:
- Introduce a new holding implementation,
MyTransferable
, which extends the Daml Finance Transferable holding implementation. This new implementation differs in that it creates aMyTransferableTransferEvent
contract instance with each transfer. - Replace the existing HoldingFactory
instance of the custodian with a new, compatible
MyHoldingFactory
for theMyTransferable
holding implementation. - Demonstrate that an upgrade happens upon a transfer of an old holding.
Run the Script¶
You can execute this tutorial using the runUpgradeHolding
script found in the
UpgradeHolding.daml
module. We’ll examine the script step-by-step to demonstrate how it works in
practice.
Setup¶
The script begins with runSetupAccountsAndHoldings
, initializing parties (a custodian Bank and
its clients, Alice and Bob), an account factory for the Bank, accounts for Alice and Bob, a holding
factory for the Bank, and a holding for Alice:
SetupState
{ bank
; bankHoldingFactory
; alice
; aliceAccount
; aliceTransferableCid
; bob
; bobAccount
; allClients
} <- runSetupAccountsAndHoldings
Initially, both the holding and holding factory are in the old version. The new MyTransferable
and MyHoldingFactory
implementations are available in the MyHolding.daml
module.
Create a New Holding Factory¶
To avoid creating holdings with the old implementation, we archive the Bank’s holding factory:
removeHoldingFactory bankHoldingFactory
Subsequently, we create a new holding factory with the same key for the Bank:
myHoldingFactory <- createMyHoldingFactory $
MyHoldingFactory with
provider = bank
id = Id "Holding Factory"
observers = allClients
Note on Upgrade Rule¶
Unlike the account upgrade tutorial, this process does not require an upgrade rule contract.
Client Upgrades¶
We let Alice transfer her holding to Bob:
Some _ <- queryContractId alice $ fromInterfaceContractId @Transferable.T aliceTransferableCid
bobHoldingCid <- submit alice do
exerciseCmd aliceTransferableCid
Transferable.Transfer with
actors = singleton alice
newOwnerAccount = bobAccount
Some _ <- queryContractId bob $ fromInterfaceContractId @MyTransferable bobHoldingCid
As a result, Alice’s existing holding is debited and Bob is credited a holding of the new version.
Summary¶
Upon completing this tutorial, you should have a clear understanding of how to implement lazy upgrades for holdings. The essential points to remember are:
- The old holding factory is to be replaced with a new one having the same key.
- Upgrades of holdings occur automatically during debiting and crediting actions, such as during transfers and settlement processes, facilitating a lazy upgrade approach.