Module 0x2::kiosk_extension
This module implements the Kiosk Extensions functionality. It allows exposing previously protected (only-owner) methods to third-party apps.
A Kiosk Extension is a module that implements any functionality on top of the Kiosk without discarding nor blocking the base. Given that Kiosk itself is a trading primitive, most of the extensions are expected to be related to trading. However, there's no limit to what can be built using the kiosk_extension module, as it gives certain benefits such as using Kiosk as the storage for any type of data / assets.
Flow:
- An extension can only be installed by the Kiosk Owner and requires an authorization via the KioskOwnerCap.
- When installed, the extension is given a permission bitmap that allows it to perform certain protected actions (eg place, lock). However, it is possible to install an extension that does not have any permissions.
- Kiosk Owner can disable the extension at any time, which prevents it from performing any protected actions. The storage is still available to the extension until it is completely removed.
- A disabled extension can be enabled at any time giving the permissions back to the extension.
- An extension permissions follow the all-or-nothing policy. Either all of the requested permissions are granted or none of them (can't install).
Examples:
- An Auction extension can utilize the storage to store Auction-related data while utilizing the same Kiosk object that the items are stored in.
- A Marketplace extension that implements custom events and fees for the default trading functionality.
Notes:
-
Trading functionality can utilize the PurchaseCap to build a custom logic around the purchase flow. However, it should be carefully managed to prevent asset locking.
-
kiosk_extension is a friend module to kiosk and has access to its internal functions (such as place_internal and lock_internal to implement custom authorization scheme for place and lock respectively).
- [Flow:](#@Flow:_0)
- [Examples:](#@Examples:_1)
- [Notes:](#@Notes:_2)
use 0x2::bag;
use 0x2::dynamic_field;
use 0x2::kiosk;
use 0x2::object;
use 0x2::transfer_policy;
use 0x2::tx_context;
Struct Extension
The Extension struct contains the data used by the extension and the configuration for this extension. Stored under the ExtensionKey dynamic field.
struct Extension has store
Fields
Struct ExtensionKey
The ExtensionKey is a typed dynamic field key used to store the extension configuration and data. Ext is a phantom type that is used to identify the extension witness.
struct ExtensionKey<Ext> has copy, drop, store
Fields
Constants
Trying to add an extension while not being the owner of the Kiosk.
const ENotOwner: u64 = 0;
Extension is trying to access a permissioned action while not having the required permission.
const EExtensionNotAllowed: u64 = 2;
Extension is not installed in the Kiosk.
const EExtensionNotInstalled: u64 = 3;
Value that represents the lock and place permission in the permissions bitmap.
const LOCK: u128 = 2;
Value that represents the place permission in the permissions bitmap.
const PLACE: u128 = 1;
Function add
Add an extension to the Kiosk. Can only be performed by the owner. The extension witness is required to allow extensions define their set of permissions in the custom add call.
public fun add<Ext: drop>(_ext: Ext, self: &mut kiosk::Kiosk, cap: &kiosk::KioskOwnerCap, permissions: u128, ctx: &mut tx_context::TxContext)
Implementation
Function disable
Revoke permissions from the extension. While it does not remove the extension completely, it keeps it from performing any protected actions. The storage is still available to the extension (until it's removed).
public fun disable<Ext: drop>(self: &mut kiosk::Kiosk, cap: &kiosk::KioskOwnerCap)
Implementation
Function enable
Re-enable the extension allowing it to call protected actions (eg place, lock). By default, all added extensions are enabled. Kiosk owner can disable them via disable call.
public fun enable<Ext: drop>(self: &mut kiosk::Kiosk, cap: &kiosk::KioskOwnerCap)
Implementation
Function remove
Remove an extension from the Kiosk. Can only be performed by the owner, the extension storage must be empty for the transaction to succeed.
public fun remove<Ext: drop>(self: &mut kiosk::Kiosk, cap: &kiosk::KioskOwnerCap)
Implementation
Function storage
Get immutable access to the extension storage. Can only be performed by the extension as long as the extension is installed.
public fun storage<Ext: drop>(_ext: Ext, self: &kiosk::Kiosk): &bag::Bag
Implementation
Function storage_mut
Get mutable access to the extension storage. Can only be performed by the extension as long as the extension is installed. Disabling the extension does not prevent it from accessing the storage.
Potentially dangerous: extension developer can keep data in a Bag therefore never really allowing the KioskOwner to remove the extension. However, it is the case with any other solution (1) and this way we prevent intentional extension freeze when the owner wants to ruin a trade (2) - eg locking extension while an auction is in progress.
Extensions should be crafted carefully, and the KioskOwner should be aware of the risks.
public fun storage_mut<Ext: drop>(_ext: Ext, self: &mut kiosk::Kiosk): &mut bag::Bag
Implementation
Function place
Protected action: place an item into the Kiosk. Can be performed by an authorized extension. The extension must have the place permission or a lock permission.
To prevent non-tradable items from being placed into Kiosk the method requires a TransferPolicy for the placed type to exist.
public fun place<Ext: drop, T: store, key>(_ext: Ext, self: &mut kiosk::Kiosk, item: T, _policy: &transfer_policy::TransferPolicy<T>)
Implementation
Function lock
Protected action: lock an item in the Kiosk. Can be performed by an authorized extension. The extension must have the lock permission.
public fun lock<Ext: drop, T: store, key>(_ext: Ext, self: &mut kiosk::Kiosk, item: T, _policy: &transfer_policy::TransferPolicy<T>)
Implementation
Function is_installed
Check whether an extension of type Ext is installed.
public fun is_installed<Ext: drop>(self: &kiosk::Kiosk): bool
Implementation
Function is_enabled
Check whether an extension of type Ext is enabled.
public fun is_enabled<Ext: drop>(self: &kiosk::Kiosk): bool
Implementation
Function can_place
Check whether an extension of type Ext can place into Kiosk.
public fun can_place<Ext: drop>(self: &kiosk::Kiosk): bool
Implementation
Function can_lock
Check whether an extension of type Ext can lock items in Kiosk. Locking also enables place.
public fun can_lock<Ext: drop>(self: &kiosk::Kiosk): bool
Implementation
Function extension
Internal: get a read-only access to the Extension.
fun extension<Ext: drop>(self: &kiosk::Kiosk): &kiosk_extension::Extension
Implementation
Function extension_mut
Internal: get a mutable access to the Extension.
fun extension_mut<Ext: drop>(self: &mut kiosk::Kiosk): &mut kiosk_extension::Extension