## Overview At a high level, bulk coretime sales are auctions with a periodic sale mechanism which attempts to find a happy medium between effective market-driven pricing and price predictability. The sale period aligns with the length of a region of coretime as it is sold by the system. A region of coretime is in general a commodity representing a varying proportion and pattern of execution on a core for a period of time. At generation it is sold in default lengths with a full mask for a single core, but can be split/interlaced to create any permutation of the length and pattern specified by the mask. A note first about design decisions: Hardcoded parts in the pallet should be as flexible as possible, without becoming overly complicated due to generality. Most of the interesting parts of the pricing and economics should be implemented in the `PriceAdapter`, allowing the specifics of the design for runtimes in different networks to be disentangled from each other, and to allow easier experimentation without updating broker pallet versions. In RFC-1 the decision was made to go for a periodic dutch auction model for price finding within the sale period. The initial implementation also included enshrined capped renewals, allowing people who had a core to renew indefinitely and partially isolated from external upward pressure on the price. ## Price definition If we are to suggest a general `PriceAdapter` to define the price of a bulk core at some time ($p_{n}(t)$) within a periodic dutch auction sale making only minimal assumptions, we would separate it into three factors: $$ p_{n}(t) = P(...) \cdot A(...) \cdot L(t,...) $$ $P(...)$ is a function which yields a base price for the current sale period, probably based on the state of the previous sale(s) $A(...)$ is the adaptation function between one sale and the next based on the state of the previous sale(s) $L(t,...)$ is the lead in factor at a given time, which changes the base price within a sale period. This could also in general depend on other inputs from previous sale(s) ## An aside For the specific implementation initially deployed on Kusama, we can expand on the inputs to each component function $$ p_{n}(t) = P(p_{\textrm{last}_{n-1}}) \cdot A(c_{\textrm{sold}_{n-1}}, c_{\textrm{target}_{n-1}}, c_{\textrm{limit}_{n-1}}) \cdot L(t) $$ Where: $p_{n}(t)$ is the price in sale $n$ at a given point in time $t$ within the sale, $p_{\textrm{last}_{n}}$ is the price of the last core to be sold in the previous sale, $L(t)$ is a function yielding the lead-in factor at block number $t$ in the current sale, $A(...)$ adapts the price between sale n-1 and sale n using: $c_{\textrm{sold}_n}$, $c_{\textrm{target}_n}$ and $c_{\textrm{limit}_n}$, which are the cores sold, ideal number of cores, and number of cores offered respectively in sale n. Currently there is an assumption in the `AdaptPrice` interface that the `leadin_factor_at` function will be passed a fraction between 0 and 1 representing how far through the lead-in period we are. This splits the sale into two periods. There is also the concept of the interlude, which adds another period for renewals to happen. Note that there is no actual need for the lead-in period to be defined in the configuration at a pallet level, but rather could be defined in the implementation of a more general price adapter. This makes the broker pallet a general periodic sale marketplace for coretime with no preference for a given sale type. Also by allowing the renewal price to also be set in the PriceAdapter we can finish our process of making the broker pallet less opinionated and allow for different approaches to renewals from network to network. [Kusama configuration in full](https://hackmd.io/LgD1J5OnSnKK5Rv4j2-lTg) ## A new PriceAdapter The price adapter should determine three main things: 1. The base price for the current sale period 2. The renewal price in the current sale period 3. The price of a core on the open market at any given point in the sale period This removes the need for the concept of a lead-in factor from the broker pallet. ## Additional information for the price adapter Instead of only taking the state of the previous sale into consideration, we can take a sample of history to apply some smoothing with a weighted moving average. This could be applied to both the market price and renewal prices with different weightings to represent their conflicting aims: renewal: guaranteed core, price predictability -> weight towards older prices for upward trends, weight towards newer prices for downward trends open market: limit volatility sale to sale, allow for high volatility within sale periods In the open market, if multiple cores are offered and all are sold, the full set of prices at which cores were sold should be summarised by the factor used to adapt the price in the next sale, not just the lowest, or reserve price. In each sale we effectively have a sample of the population of core-buyers. In a high stats environment we would expect the median of these offers to be a good representation of the "true" market price of a core. However, since we are operating with low stats (a small number of cores in each sale), the median is not the representative price of the whole population. By taking the extreme values into consideration through some consideration of the distribution, and combining it with the mean of the successful offers for the core in the prior sale, we can calculate a meaningful correction towards the market price for the next sale. These values can be combined to give a meaningful base price for the next sale, but since we sold out of cores before the sale ended, we also are missing some information about the number of cores that would have been sold (and at what price) if we had more cores to offer. There is no pressure to vacate cores when the system starts to reach its limit - the number of free (not renewable) cores has no influence on the price in a given sale, whereas I think it should. Having a higher core liquidity is preferable with market-driven pricing and helps to keep the price of cores down in general. ## Maximum number of renewable parachains per month? FCFS, Root extrinsic to pop