Assets
Overview
Assets on Polymesh can represent any type of digitalised asset, and are originated and managed through the asset base layer logic in Polymesh.
This ensures that all assets are created in a standardised manner, allowing related functionality such as corporate actions, settlement and compliance, to function seamlessly across all assets.
Once an asset has been created, its ownership is represented via balances of that assets tokens held by different investors.
Ownership of an asset on Polymesh can be determined via its:
total supply: the total number of tokens that represent ownership in the asset
investor balances: the individual balance of each investing identity in the asset
The asset pallet documentation can be found at: https://docs.polymesh.live/pallet_asset/index.html
Polymesh allows you to manage the full lifecycle of any asset directly on the Polymesh blockchain, including the issuance, initial distribution or fund-raise of the asset and any subsequent corporate actions such as dividend payments, capital distributions or corporate ballots.
Asset tokens can be either divisible or indivisible.
Ticker Registration
Every asset on Polymesh has a unique ticker - a 12 character identifier for the asset.
Users can register a ticker, and then when they are ready create an asset associated with that registered ticker.
Ticker registrations can be transferred between identities and have an expiry date, currently set to 6 months from their initial registration.
Registering a ticker ensures no other user can issue an asset with that ticker whilst the registration is valid (i.e. has not expired).
Asset Creation
Having registered a ticker, users can then create their asset, specifying the type of the asset (e.g. Equity, Bond, Fund).
The asset is initially created with a zero total supply. For the initial issuance of the asset, see the Issuance section.
As well as being identified via a unique ticker, assets can be associated with additional external identifiers, such as ISINs, CUSIPs, CINs, LEIs and DTIs, with Polymesh validating that these identifiers are consistent (i.e. that their checksums match).
If a ticker is not currently reserved, the ticker registration is done automatically when a user creates an asset.
Documentation
Polymesh allows the issuer of an asset to associate documents with that asset.
The actual document is not stored on-chain, and instead the asset is associated with a document reference on-chain, where the reference includes a name, the URL at which the document can be found (this may be a permissioned URL requiring an investor in the asset to have some credentials to access the document), as well as an optional document type, filing date, and hash of the document contents.
Documentation can only be updated or modified by the identity that issued the corresponding asset (the asset issuer).
Ownership
All asset ownership in Polymesh is at the identity granularity. Whilst an investor can organise their assets into different portfolios under their identity, compliance is enforced at the identity level, so in order to pay or receive a particular assets token, the relevant identity must have claims that match the compliance rules specified by the asset issuer for the asset.
Asset Issuers
The asset issuer is the identity which registered the ticker and created the asset. The asset issuer can transfer ownership of an asset to another identity by issuing a TransferAsset
authorisation which must be accepted by the target identity.
The asset issuer also has some additional controls which are soley accessible to them. These include:
updating documentation and identifiers for their asset
freeze and unfreeze any transfers of their asset
add and remove compliance rules for their asset
permission venues to settle their asset
In addition an asset issuer can execute a controller transfer of their token. This allows them to force transfer ownership of their asset tokens from any investor back to the primary issuance agent of the asset. The primary issuance agent is an identity which an asset issuer specifies for their asset, and is responsible for treasury management and token distribution.
Issuance
The issuance process for assets in Polymesh allows the originator of an asset (the asset issuer) to issue and distribute their asset to investors.
Roles
Every asset, identified by its unique ticker, is associated with one or more identities:
the asset issuers identity: this is the identity that created the asset
external agents identities: these are the (optional) identities responsible for managing the asset on behalf of the issuer
External Agents
External agents are other Polymesh identities that have been granted permissions related to a particular ticker. Their role is to manage the asset on behalf of the asset issuer.
External agents can be added to an asset by the asset issuer (or an existing agent of the asset with appropriate permissions) by issuing a BecomeAgent
authorisation. The external agent identity then needs to accept this authorisation.
Each external agent can be placed into a new or existing permission group, with permissions then derived from this group for all agents within it.
There are some pre-defined agent permission groups which are:
pub enum AgentGroup {
/// Has all permissions.
Full,
/// Custom defined agent group drawn from 2).
/// The other groups have hard-coded mappings to `Permissions` in code.
Custom(AGId),
/// Manages identities of agents themselves.
ExceptMeta,
/// Agent group corresponding to a Corporate Action Agent (CAA) on Polymesh Mainnet v1.
PolymeshV1CAA,
/// Agent group corresponding to a Primary Issuance Agent (PIA) on Polymesh Mainnet v1.
PolymeshV1PIA,
}
Alternatively an asset issuer can create a new agent permission group using the Custom
enum variant, with whatever permissions are appropriate to their use-case, and then add external agents related to their asset to this group.
Process
Once an asset issuer has created and configured their asset, they can then issue tokens representing ownership in the asset to themselves or a distribution external agent of the asset.
The agent can then distribute those asset tokens to investors directly or via an security token offering, in both cases using the settlement engine.
This approach allows a clean separation between the issuance process, which bypasses both the compliance and settlement engine and is restricted to only issuance to the configured agents, and the distribution process which uses both the compliance and settlement engines.
Checkpoints
An asset checkpoint is a collection of records representing the balances of that asset at a given time. The balances recorded are the total asset balance and all the balances held by identities.
This is useful for capital distributions and corporate ballots where we need a consistent set of balances as of some specific time (or block).
Creating a checkpoint
There are two ways to create a checkpoint.
Call the dispatchable
create_checkpoint(ticker)
in theasset
pallet. This creates a checkpoint for the asset ofticker
. The total balance is recorded instantly, and each balance held an identity is recorded just before the next transaction to or from that identity. Since the balances of identities are not recorded instantly, we call this process lazy checkpointing. A consequence of this method is that no records are made if there are no transactions.Create a checkpoint schedule using the dispatchable
create_checkpoint_schedule(ticker, schedule)
in the same pallet. A schedule consists of a starting timestamp in seconds since the UNIX epoch and a period for recurring the checkpoint at regular intervals. The period is a multiple of one of seconds, minutes, hours, days, weeks, months, or years. If the period has zero length then the checkpoint schedule it defines is non-recurring and the only checkpoint it contains is the one at the start. Scheduled checkpoints are created automatically at times defined by the schedule but are otherwise identical in nature to manual checkpoints. Scheduling of the next checkpoint happens lazily as well, on an asset transaction or minting. If there are no such transactions by the time a checkpoint is due, it does not get rescheduled, which is fine with the scheduler since it takes into account any missed checkpoints.
Checkpoint periods
There are two kinds of periods: ones of fixed length if measured in seconds -- multiples of seconds, minutes, hours, days or weeks -- and ones of variable length -- multiples of months or years.
When computing the time when the next checkpoint is due, if the period is fixed the runtime adds the length of that period in seconds to the time when the last checkpoint was due.
If the period is variable, the next timestamp computation takes into account the day of the month at the start of the schedule. Every checkpoint gets a day of the month that is at most that of the start of the schedule.
For example, assume we have the checkpoint schedule that
starts on 00:01:00 the 31st of January, 2021 UTC and
has a period of one month.
The checkpoint timestamps are going to be
2021-01-31 00:01:00
2021-02-28 00:01:00
2021-03-31 00:01:00
2020-04-30 00:01:00
and so on.
Accessing an existing checkpoint
The checkpoints of an asset form a sequence that is indexed starting from 1. The total balance and balances of identities are stored at these indices.
To read the total supply of ticker
at checkpoint index i
one calls the getter
total_supply_at(ticker, i)
in the asset pallet. The getter returns the value directly from runtime
storage.
To read the checkpoint balance of identity
one calls the function get_balance_at(ticker,
identity, i)
in the same pallet. This function returns the checkpoint balance at i
by searching
for the least checkpoint index greater or equal to i
or, if no such record exists due to the
absence of transactions, the current asset balance of identity
.
The time at which a checkpoint was made is stored in a map indexed by checkpoint sequence numbers and can be read knowing the required sequence number.