Ownable
Ownable is single-owner authorization for Daml. It is the Daml analogue of OpenZeppelin's Ownable2Step: one owner party at a time, a two-step ownership transfer, and a renounce path.
The package has no dependency on other OpenZeppelin packages.
Experimental. Version 0.x, unaudited, and subject to a redesign before
release. Source:
experiments/access/ownable-v1
in OpenZeppelin/canton-contracts.
import OpenZeppelin.OwnableV1Why Transfer Has Two Steps
In Solidity, transferOwnership(newOwner) is one call. Daml cannot do this. The owner is a signatory of the Ownership contract, and Daml requires the authority of every signatory to create a contract. The current owner alone cannot make another party a signatory.
Transfer is therefore an offer and an acceptance. The owner creates an OwnershipOffer, and the new owner accepts it. As a result, no party becomes owner without its agreement.
While an offer is pending, no Ownership contract exists. The offer archives the Ownership contract. Acceptance creates a new one for the new owner. A decline or a withdrawal creates a new one for the current owner. Applications that require an active Ownership contract must handle this period.
Ownership is not bound to a specific resource. The application must define which Ownership contract controls each protected resource.
Templates
Ownership
Ownership of a resource by one party.
| Field | Type | Description |
|---|---|---|
owner | Party | The current owner. |
Signatory owner, no observers. Other parties read the contract through explicit disclosure. owner controls both choices, and both are consuming.
Ownership_OfferOwnership(takesnewOwner : Party, returnsContractId OwnershipOffer): start a transfer tonewOwner. Fails ifnewOwneris the current owner.Ownership_RenounceOwnership(returns()): give up ownership permanently (therenounceOwnershipanalogue). NoOwnershipcontract remains.
OwnershipOffer
A pending transfer.
| Field | Type | Description |
|---|---|---|
owner | Party | The owner that made the offer. |
newOwner | Party | The party that can accept. |
Signatory owner, observer newOwner. All choices are consuming and take no arguments.
| Choice | Controller | Result | Description |
|---|---|---|---|
OwnershipOffer_Accept | newOwner | ContractId Ownership | Creates Ownership for newOwner, with newOwner as signatory. |
OwnershipOffer_Decline | newOwner | ContractId Ownership | Returns ownership to owner. |
OwnershipOffer_Withdraw | owner | ContractId Ownership | Returns ownership to owner. |
A signatory can archive Ownership or OwnershipOffer directly. This leaves no Ownership contract, so the resource has no owner.
Transferring Ownership
Each step is a separate submission by a different party. In Daml Script:
-- alice, the current owner, makes the offer
offerCid <- submit alice do
exerciseCmd ownershipCid Ownership_OfferOwnership with newOwner = bob
-- bob accepts and becomes the owner
newOwnershipCid <- submit bob do
exerciseCmd offerCid OwnershipOffer_AcceptErrors
| Message | Cause |
|---|---|
Ownable: new owner is the current owner | The offer names the current owner. |
Related
- Access Control when more than one party or action needs separate authorization.
- Pausable for an emergency stop.