Locking by state¶
The original Coin template is shown below. This is the basis on which to implement locking by state
template Coin with owner: Party issuer: Party amount: Decimal delegates : [Party] where signatory issuer, owner observer delegates controller owner can Transfer : ContractId TransferProposal with newOwner: Party do create TransferProposal with coin=this; newOwner --a coin can only be archived by the issuer under the condition that the issuer is the owner of the coin. This ensures the issuer cannot archive coins at will. controller issuer can Archives : () do assert (issuer == owner)
In its original form, all choices are actionable as long as the contract is active. Locking by State requires introducing fields to track state. This allows for the creation of an active contract in two possible states: locked or unlocked. A Daml modeler can selectively make certain choices actionable only if the contract is in unlocked state. This effectively makes the asset lockable.
The state can be stored in many ways. This example demonstrates how to create a LockableCoin through a party. Alternatively, you can add a lock contract to the asset contract, use a boolean flag or include lock activation and expiry terms as part of the template parameters.
Here are the changes we made to the original Coin contract to make it lockable.
- Add a locker party to the template parameters.
- Define the states.
- if owner == locker, the coin is unlocked
- if owner != locker, the coin is in a locked state
- The contract state is checked on choices.
- Transfer choice is only actionable if the coin is unlocked
- Lock choice is only actionable if the coin is unlocked and a 3rd party locker is supplied
- Unlock is available to the locker party only if the coin is locked
template LockableCoin with owner: Party issuer: Party amount: Decimal locker: Party where signatory issuer signatory owner ensure amount > 0.0 --Transfer can happen only if it is not locked controller owner can Transfer : ContractId TransferProposal with newOwner: Party do assert (locker == owner) create TransferProposal with coin=this; newOwner --Lock can be done if owner decides to bring a locker on board Lock : ContractId LockableCoin with newLocker: Party do assert (newLocker /= owner) create this with locker = newLocker --Unlock only makes sense if the coin is in locked state controller locker can Unlock : ContractId LockableCoin do assert (locker /= owner) create this with locker = owner
Locking By State Diagram
- It requires changes made to the original contract template. Furthermore you should need to change all choices intended to be locked.
- If locking and unlocking terms (e.g. lock triggering event, expiry time, etc) need to be added to the template parameters to track the state change, the template can get overloaded.