Market Pallet

Table of Contents

Overview

The purpose of the pallet is to manage storage deals between storage market participants and to track their funds. Market Pallet is tightly coupled with Storage Provider Pallet because it's a source of truth for deals. Storage Provider Pallet cannot exist without deal information from Market Pallet.

Extrinsics*

add_balance

Reserves a given amount of currency for usage in the Storage Market.

The reserved amount will be considered free until it is used in a deal when moved to locked and used to pay for the deal.

NameDescriptionType
amountThe amount to be reservedPositive integer

Example

Using the storagext-cli to add 1_000_000_0001 Plancks to Alice's account with the following command2:

storagext-cli --sr25519-key "//Alice" market add-balance 1000000000
1
This value is the minimum amount due to Polkadot's existential deposit.
More information available in: <https://support.polkadot.network/support/solutions/articles/65000168651-what-is-the-existential-deposit->.
2

Read more about the add-balance command in Storagext CLI/Subcommand market/add-balance.

withdraw_balance

Withdraws funds from the Storage Market.

The funds will be withdrawn from the free balance, meaning that the amount must be less than or equal to free and greater than 0 (\({free} \ge {amount} \gt 0\)).

NameDescriptionType
amountThe amount to be withdrawnPositive integer

Example

Using the storagext-cli to withdraw 10000 Plancks from Alice's free balance using the following command3:

storagext-cli --sr25519-key "//Alice" market withdraw-balance 10000
3

Read more about the withdraw-balance command in Storagext CLI/Subcommand market/withdraw-balance.

publish_storage_deals

Publishes list of deals to the chain.

This extrinsic must be called by a storage provider.

NameDescriptionType
proposalSpecific deal proposal, a JSON objectJSON object, specified in the deal proposal components section
client_signatureClient signature of this specific deal proposalMultiSignature, meaning a 64-byte array for Sr25519 and Ed25519 signatures and 65-byte array for ECDSA signatures

The client_signature, as the name indicates, is generated by the client by signing the deal proposal with their private key — the storagext-cli does this for the user automatically4. This signature ensures that the storage provider cannot forge a deal with an arbitrary client. The type of signature is dependent on the key the signer has, currently supported key types are Sr25519, ECDSA and Ed25519.

This step corresponds to the "sign & send proposal" step in the deal overview.

Deal Proposal Components

NameDescriptionType
piece_cidByte encoded CIDCID
piece_sizeSize of the piecePositive integer
clientSS58 address of the storage clientSS58 address
providerSS58 address of the storage providerSS58 address
labelArbitrary client chosen labelString, with a maximum length of 128 characters
start_blockBlock number on which the deal should startPositive integer
end_blockBlock number on which the deal should endPositive integer, end_block > start_block
storage_price_per_blockPrice for the storage specified per block5Positive integer, in Plancks
provider_collateralCollateral which is slashed if the deal failsPositive integer, in Plancks
stateDeal state. Can only be set to PublishedString

See the original Filecoin specification for details.

Example

Using the storagext-cli to publish deals with //Alice as the storage provider and //Charlie as the client by running the following command6:

storagext-cli --sr25519-key "//Alice" market publish-storage-deals \
  --client-sr25519-key "//Charlie" \
  "@deals.json"

Where deals.json is a file with contents similar to:

[
  {
    "piece_cid": "bafk2bzacecg3xxc4f2ql2hreiuy767u6r72ekdz54k7luieknboaakhft5rgk",
    "piece_size": 1337,
    "client": "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
    "provider": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
    "label": "Super Cool (but secret) Plans for a new Polkadot Storage Solution",
    "start_block": 69,
    "end_block": 420,
    "storage_price_per_block": 15,
    "provider_collateral": 2000,
    "state": "Published"
  },
  {
    "piece_cid": "bafybeih5zgcgqor3dv6kfdtv3lshv3yfkfewtx73lhedgihlmvpcmywmua",
    "piece_size": 1143,
    "client": "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
    "provider": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
    "label": "List of problematic (but flying) Boeing planes",
    "start_block": 1010,
    "end_block": 1997,
    "storage_price_per_block": 1,
    "provider_collateral": 3900,
    "state": "Published"
  }
]
Notice how the CLI command doesn't take the client_signature parameter but a keypair that can sign it.

We are aware that this is not secure. However, the system is still under development and is not final; it is a testing tool.

4

Take into account that the CLI is currently for demo purposes, the authors are aware that the command isn't safe since it requires the private keys of both parties.

5

The formula to calculate the total price is as follows: \[total\_price = (end\_block - start\_block) * storage\_price\_per\_block\].

6

Read more about the publish-storage-deals command in Storagext CLI/Subcommand market/publish-storage-deals.

settle_deal_payments

Settle specified deals between providers and clients.

Both clients and providers can call this extrinsic. However, since the settlement is the mechanism through which the provider gets paid, a client has no reason to call this extrinsic. Non-existing deal IDs will be ignored.

NameDescriptionType
deal_idsList of the deal IDs to be settledArray of integers

Example

Using the storagext-cli to settle deal payments for IDs 97, 1010, 1337 and 42069 using the following command7:

storagext-cli --sr25519-key "//Alice" market settle-deal-payments 97 1010 1337 42069
7

Read more about the settle-deal-payments command in Storagext CLI/Subcommand market/settle-deal-payments

Events

The Market Pallet emits the following events:

  • BalanceAdded - Indicates that some balance was added as free to the Market Pallet account for usage in the storage market.
    • who - SS58 address of then account which added balance
    • amount - Amount added
  • BalanceWithdrawn - Some balance was transferred (free) from the Market Account to the Participant's account.
    • who - SS58 address of the account which had withdrawn the balance
    • amount - Amount withdrawn
  • DealPublished - Indicates that a deal was successfully published with publish_storage_deals.
    • deal_id - Unique deal ID
    • client - SS58 address of the storage client
    • provider - SS58 address of the storage provider
  • DealActivated - Deal's state has changed to Active.
    • deal_id - Unique deal ID
    • client - SS58 address of the storage client
    • provider - SS58 address of the storage provider
  • DealsSettled - Published after the settle_deal_payments extrinsic is called. Indicates which deals were successfully and unsuccessfully settled.
    • successful - List of deal IDs that were settled
    • unsuccessful - List of deal IDs with the corresponding errors
  • DealSlashed - Is emitted when some deal expired.
    • deal_id - Deal ID that was slashed
  • DealTerminated - A deal was voluntarily or involuntarily terminated.
    • deal_id - Terminated deal ID
    • client - SS58 address of the storage client
    • provider - SS58 address of the storage provider

Errors

The Market Pallet actions can fail with following errors:

  • InsufficientFreeFunds - Market participants do not have enough free funds.
  • NoProposalsToBePublished - publish_storage_deals was called with an empty list of deals.
  • ProposalsPublishedByIncorrectStorageProvider - Is returned when calling publish_storage_deals and the deals in a list are not published by the same storage provider.
  • AllProposalsInvalid - publish_storage_deals call was supplied with a list of deals which are all invalid.
  • DuplicateDeal - There is more than one deal with this ID in the Sector.
  • DealNotFound - Tried to activate a deal that is not in the system.
  • DealActivationError - Tried to activate a deal, but data was malformed.
    • Invalid specified provider.
    • The deal already expired.
    • Sector containing the deal expires before the deal.
    • Invalid deal state.
    • Deal is not pending.
  • DealsTooLargeToFitIntoSector - Sum of all deals piece sizes for a sector exceeds sector size. The sector size is based on the registered proof type. We currently only support registered StackedDRG2KiBV1P1 proofs, which have 2KiB sector sizes.
  • TooManyDealsPerBlock - Tried to activate too many deals at a given start_block.
  • UnexpectedValidationError - publish_storage_deals's core logic was invoked with a broken invariant that should be called by validate_deals. Please report an issue to the developers.
  • DealPreconditionFailed - Due to a programmer bug. Please report an issue to the developers.

Constants

NameDescriptionValue
MaxDealsHow many deals can be published in a single batch of publish_storage_deals.128
MaxDealsPerBlockMaximum deals that can be scheduled to start at the same block.128
MinDealDurationMinimum time an activated deal should last.5 Minutes (50 Blocks)
MaxDealDurationMaximum time an activated deal should last.180 Minutes (1800 Blocks)