0x0::royalty

Module of Collection RoyaltyDomain

RoyaltyDomain allows creators to define custom royalty strategies, collect royalties for their collections. Additionally, creators and their respective royalty share are tracked.

royalty does not provide a generic calculate function that takes into account all royalty strategies defined on the domain, as the OriginByte standard does not know how to read strategies not otherwise defined by it.

The module relies on an external contract to drive the royalty gathering and dirtribution flow.

Structs

royalty::RoyaltyDomain has store

Fields:

Name Type Description
strategies object::UID

Royalty strategies

aggregations object::UID

Aggregates received royalties across different coins

royalty_shares_bps vec_map::VecMap<address, u16>

Royalty share received by addresses

RoyaltyDomain stores royalty strategies for Collection and distributes them among creators

Usage

RoyaltyDomain can only calculate royalties owed and distribute them to shareholders, as a result, it relies on trusted price execution.

The usage example shows how to derive the owed royalties from the example collection, Suimarines, which uses TradePayment as the price oracle, but is also responsible for deconstructing it. For more information read royalties.

module nft_protocol::suimarines {
    struct Witness has drop {}

    public entry fun collect_royalty<FT>(
        payment: &mut TradePayment<SUIMARINES, FT>,
        collection: &mut Collection<SUIMARINES>,
        ctx: &mut TxContext,
    ) {
        let b = royalties::balance_mut(Witness {}, payment);

        let domain = royalty::royalty_domain(collection);
        let royalty_owed =
            royalty::calculate_proportional_royalty(domain, balance::value(b));

        royalty::collect_royalty(collection, b, royalty_owed);
        royalties::transfer_remaining_to_beneficiary(Witness {}, payment, ctx);
    }
}

royalty::Witness has drop

Witness used to authenticate witness protected endpoints

Methods

public fun new_empty(ctx: &mut tx_context::TxContext): 
    royalty::RoyaltyDomain

Creates an empty RoyaltyDomain object

By not attributing any addresses, nobody will ever be able to claim royalties from this RoyaltyDomain object.

public fun from_address(
    who: address,
    ctx: &mut tx_context::TxContext,
): royalty::RoyaltyDomain

Creates a RoyaltyDomain object with only one address attribution

Only the single address will be able to claim royalties from this RoyaltyDomain object.

public fun from_shares(
    royalty_shares_bps: vec_map::VecMap<address, u16>,
    ctx: &mut tx_context::TxContext,
): royalty::RoyaltyDomain

Creates a RoyaltyDomain with multiple attributions

Attributed addresses will be able to claim royalties weighted by their share in the total royalties.

Panics

Panics if total sum of creator basis point share is not equal to 10000

public fun borrow_share(
    domain: &royalty::RoyaltyDomain,
    who: &address,
): &u16

Returns the Creator type for the given address

Panics

Panics if the provided address is not an attributed creator

public fun contains_share(
    domain: &royalty::RoyaltyDomain,
    who: &address,
): bool

Returns true when address is a defined creator

public fun contains_shares(domain: &royalty::RoyaltyDomain): 
    bool

Returns true when a share attribution exists

public fun borrow_shares(domain: &royalty::RoyaltyDomain): 
    &vec_map::VecMap<address, u16>

Returns the list of creators defined on the CreatorsDomain

public fun add_share(
    domain: &mut royalty::RoyaltyDomain,
    who: address,
    share: u16,
    ctx: &mut tx_context::TxContext,
)

Attribute a share of royalties to an address

This must be done by an address which already has an attribution and partially gives up a share of their royalties for the benefit of the new attribution. Ensures that the total sum of shares remains constant.

Panics

Panics if the transaction sender does not have a large enough royalty share to transfer to the new creator or is not attributed in the first place.

public fun add_share_to_empty(
    domain: &mut royalty::RoyaltyDomain,
    who: address,
)

Attribute royalties to an address

Panics

Panics if a share attribution already exists

public fun add_shares_to_empty(
    domain: &mut royalty::RoyaltyDomain,
    royalty_shares_bps: vec_map::VecMap<address, u16>,
)

Attribute royalties to addresses

Panics

Panics if a share attribution already exists

public fun remove_creator_by_transfer(
    domain: &mut royalty::RoyaltyDomain,
    to: address,
    ctx: &mut tx_context::TxContext,
)

Remove a share attribution from an address and transfer attribution to another address

Shares of the removed attribution are allocated to the provided address, ensures that the total sum of shares remains constant.

Panics

Panics if attempting to remove attribution which doesn't belong to the transaction sender

public fun add_royalty_strategy<Strategy: drop + store>(
    domain: &mut royalty::RoyaltyDomain,
    strategy: Strategy,
)

Add a generic royalty strategy

Royalty strategies which are not part of the OriginByte standard must implement their own calculation methods. Prefer using add_proportional_royalty and add_constant_royalty if only adding standard royalty strategies.

Panics

Panics if royalty strategy of the same type was already registered

public fun remove_strategy<Strategy: drop + store>(
    domain: &mut royalty::RoyaltyDomain,
): Strategy

Remove a royalty strategy

Prefer using remove_proportional_royalty and remove_constant_royalty if only removing standard royalty strategies.

Panics

Panics if strategy was not defined

public fun contains_strategy<Strategy: drop + store>(
    domain: &royalty::RoyaltyDomain,
): bool

Check whether a royalty strategy is defined

public fun borrow_strategy<Strategy: drop + store>(
    domain: &royalty::RoyaltyDomain,
): &Strategy

Borrow a royalty strategy

Panics

Panics if strategy was not defined

public fun borrow_strategy_mut<Strategy: drop + store>(
    domain: &mut royalty::RoyaltyDomain,
): &mut Strategy

Mutably borrow a royalty strategy

Panics

Panics if strategy was not defined

public fun add_proportional_royalty(
    domain: &mut royalty::RoyaltyDomain,
    royalty_fee_bps: u64,
)

Add proportional royalty policy

public fun add_constant_royalty(
    domain: &mut royalty::RoyaltyDomain,
    royalty_fee: u64,
)

Add constant royalty policy

public fun remove_proportional_royalty(
    domain: &mut royalty::RoyaltyDomain,
): royalty_strategy_bps::BpsRoyaltyStrategy

Remove proportional royalty policy

public fun remove_constant_royalty(
    domain: &mut royalty::RoyaltyDomain,
): royalty_strategy_constant::ConstantRoyaltyStrategy

Remove constant royalty policy

public fun calculate_proportional_royalty(
    domain: &royalty::RoyaltyDomain,
    amount: u64,
): u64

Calculate how many tokens are due for the defined proportional royalty strategy.

Zero if strategy is undefined.

public fun calculate_constant_royalty(
    domain: &royalty::RoyaltyDomain,
): u64

Calculate how many tokens are due for the defined constant royalty strategy.

Zero if strategy is undefined.

public fun collect_royalty<C, FT>(
    collection: &mut collection::Collection<C>,
    source: &mut balance::Balance<FT>,
    amount: u64,
)

Collects an amount of tokens from the provided balance into the aggregate balance of the RoyaltyDomain registered on the Collection

Requires that a RoyaltyDomain is registered on the collection

public entry fun distribute_royalties<C, FT>(
    collection: &mut collection::Collection<C>,
    ctx: &mut tx_context::TxContext,
)

Distributes the aggregated royalties for fungible token, FT, among the creators defined in CreatorsDomain.

This endpoint is permissionless and can be called by anyone.

Panics

Panics if there is no aggregate for token FT.

public fun distribute_balance<FT>(
    shares: &vec_map::VecMap<address, u16>,
    aggregate: &mut balance::Balance<FT>,
    ctx: &mut tx_context::TxContext,
)

Distributes the contents of a Balance<FT> among the addresses defined in VecMap<address, u16>

VecMap<address, u16> is treated as the basis point share in total royalties due to the address.

public fun royalty_domain<C>(
    collection: &collection::Collection<C>,
): &royalty::RoyaltyDomain

Get reference to RoyaltyDomain

public fun royalty_domain_mut<C>(
    _witness: witness::Witness<C>,
    collection: &mut collection::Collection<C>,
): &mut royalty::RoyaltyDomain

Get mutable reference to RoyaltyDomain

Requires that CreatorsDomain is defined and sender is a creator

public fun add_royalty_domain<C, W>(
    witness: &W,
    collection: &mut collection::Collection<C>,
    domain: royalty::RoyaltyDomain,
)

Registers RoyaltyDomain on the given Collection