Lock 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
choice Transfer : ContractId TransferProposal
with newOwner: Party
controller owner
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.
choice Archives
: ()
controller issuer
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
observer locker
ensure amount > 0.0
--Transfer can happen only if it is not locked
choice Transfer : ContractId TransferProposal
with newOwner: Party
controller owner
do
assert (locker == owner)
create TransferProposal
with coin=this; newOwner
--Lock can be done if owner decides to bring a locker on board
choice Lock : ContractId LockableCoin
with newLocker: Party
controller owner
do
assert (newLocker /= owner)
create this with locker = newLocker
--Unlock only makes sense if the coin is in locked state
choice Unlock
: ContractId LockableCoin
controller locker
do
assert (locker /= owner)
create this with locker = owner
Locking By State Diagram
![Locking by State diagram showing that the transfer choice is actionable only if the LockableCoin is unlocked.](../../../_images/lockingByStateChange.png)
Trade-offs¶
- 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.