-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Walkthrough & initial simplification for Shannon (#3)
This was a collaboration between @RawthiL and @Olshansk to go through the notebooks and understand how the repo can be simplified into an initial version that can go to production. See pokt-network/poktroll#708 for reference. --------- Co-authored-by: Ramiro Rodriguez Colmeiro <[email protected]>
- Loading branch information
Showing
17 changed files
with
5,548 additions
and
3,252 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,5 @@ untracked | |
.vscode | ||
__pycache__ | ||
venv | ||
.DS_store | ||
.venv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Tokenomics Models <!-- omit in toc --> | ||
|
||
This folder contains three different tokenomic models: | ||
|
||
- [Shane](#shane) | ||
- [MINT-V2](#mint-v2) | ||
- [Token Logic Modules](#token-logic-modules) | ||
- [Core Model](#core-model) | ||
- [Boosts](#boosts) | ||
|
||
## Shane | ||
|
||
A python version of the final [spreadsheet model from Shane](https://docs.google.com/spreadsheets/d/1-_G8VCQ7WbytNmps_N6LhQJatPN3CvV6z2_e0bN9cC0/edit). | ||
|
||
The model implements the initial concept of Token Logic Modules (TLMs). | ||
|
||
## MINT-V2 | ||
|
||
This is an upgrade to the [MINT model](https://forum.pokt.network/t/mint-incentivizing-network-transformation-mint/4522) featuring non-linear parameter modulation and a normalization mechanic based on the entropy concept [described here](https://forum.pokt.network/t/v1-how-to-enforce-fairness-and-decentralization-a-first-approach/3992). | ||
|
||
## Token Logic Modules | ||
|
||
_tl;dr Independent decoupled tokenomic modules._ | ||
|
||
This is an composed version of the two models above. While more complex, it enables the implementation of arbitrary politics that can be applied or removed without cross-talk. For example, if we want to increase the DAO income by means of over-minting, we don't need to change the base minting, increase the DAO take and reduce the Validators, Sources and Servicers take, instead, we would only increase the DAO boost module (or add a new one). | ||
|
||
The concept of the TLM is described in the following figure: | ||
 | ||
The TLM model is composed of a single `Core Model` and multiple `Boosts`. | ||
|
||
### Core Model | ||
|
||
The `Core Model` represents the ultimate tokenomics of the network, meaning, self-sustained economy with `mint == burn` (or very little supply growth/attrition). This module will mint proportional to the burn and divide the rewards among actors following a share table similar to Morse. | ||
|
||
### Boosts | ||
|
||
The `Boosts` (DAO, Validator, Supplier, Source) are modules that provide extra minting to a given actor. A module has the following characteristics: | ||
|
||
- _Recipient_ : The `network actor` that will receive the boost. A TLM can only affect a single actor. | ||
- _Condition_ : A set of thresholds over a given network parameter that determine whether to apply or not the TLM. | ||
- _Minting_ : The logic required to produce the minting. This function can be arbitrary, the only condition is that it should provide a value for each service in the network as return value. | ||
- _Budget_ : The maximum amount of coins that a module can produce. This is potentially optional, but is useful to control overall minting. For example, a given module can only mint up to a given percentage of the total supply (annualized) or a fixed amount of POKT coins. | ||
|
||
After all the TLMs are executed, the proposed minting values are processed by the `global module`. This module applies base minting values (for example a base minting of 15000 USD to all suppliers) and controls the total supply growth (a safe mechanisms to keep supply growth controlled). | ||
|
||
Finally the minting budget is processed by the normalization and penalties module. This module takes the potential minting and strictly reduces it, this means that this module will never output more coins (in total) than the previous one. Here the service imbalance correction and under-provided minting limits are implemented. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
from dataclasses import dataclass | ||
from typing import Callable, List | ||
|
||
import math_utils | ||
import pandas as pd | ||
|
||
|
||
@dataclass | ||
class Condition: | ||
# TODO: Make ENUM for metrics | ||
metric: str # total_cus, sum_emas_relays, etc... | ||
low_threshold: float | ||
high_threshold: float | ||
|
||
|
||
@dataclass | ||
class Point: | ||
x: float | ||
y: float | ||
|
||
|
||
@dataclass | ||
class Variables: | ||
x: str | ||
y: str | ||
|
||
|
||
@dataclass | ||
class Budget: | ||
type: str | ||
value: float | ||
|
||
|
||
@dataclass | ||
class Parameters: | ||
start: Point | ||
end: Point | ||
variables: Variables | ||
budget: Budget | ||
|
||
|
||
@dataclass | ||
class TLMBoost: | ||
name: str | ||
actor: str # make this an enum too | ||
conditions: List[Condition] | ||
minting_func: Callable | ||
parameters: Parameters | ||
|
||
|
||
# TODO_FUTURE: | ||
# 1. report card how well you did | ||
# 2. punch card: how much you did -> EMA of # relays | ||
# -> Low -> shitty job based on off chain (implicit QoS) | ||
# -> high -> good job based on off chain (implicit QoS) | ||
|
||
|
||
def boost_cuttm_f_CUs_nonlinear(tlm_per_service_df: pd.DataFrame, network_macro: dict, params: dict) -> pd.Series: | ||
""" | ||
This is a basic non-linear boost functions that modifies the CUTTM as a | ||
function of the CUs: | ||
CUTTM = f(CU) | ||
This is the result of separating the MINT-V2 mechanisms into stand-alone | ||
modules. | ||
Goal of this function: Trying to achieve a boost value for the CUTTM | ||
Boost should be near zero when in equilibrium. | ||
""" | ||
|
||
# Assert that the TLM config is correct | ||
assert params.variables.x == "total_cus" | ||
assert params.variables.y == "CUTTM" | ||
|
||
# Calculate the non-linear parameters of this boost | ||
a_param, b_param = math_utils.get_non_linear_params( | ||
[params.start.x, params.start.y], | ||
[params.end.x, params.end.y], | ||
) | ||
# Calculate the parameter cap | ||
param_cap = None | ||
if params.budget.type == "annual_supply_growth": | ||
# Calculate annualized growth | ||
param_cap = [ | ||
((params.budget.value / 100.0) * network_macro["total_supply"]) / (network_macro["total_cus"] * 365.2) | ||
] | ||
else: | ||
raise ValueError('Budget type "%s" not supported' % params.budget.type) | ||
# Calculate the parameter to use | ||
param_use = math_utils.calc_non_linear_param( | ||
[network_macro[params.variables.x]], | ||
a_param, | ||
b_param, | ||
params.end.x, | ||
bootstrap_start=params.start.x, | ||
max_param=param_cap, | ||
) | ||
|
||
# Calculate (maximum) total minted in each service | ||
# The same as the core TLM (or any TLM) this value will be potentially reduced | ||
return param_use * tlm_per_service_df["cu_per_node"] * tlm_per_service_df["active_nodes"] | ||
|
||
|
||
dao_boost = TLMBoost( | ||
name="DAO Boost", | ||
actor="DAO", | ||
conditions=[Condition(metric="total_cus", low_threshold=0, high_threshold=2500 * 1e9)], | ||
minting_func=boost_cuttm_f_CUs_nonlinear, | ||
parameters=Parameters( | ||
start=Point(x=250 * 1e9, y=5e-9), | ||
end=Point(x=2500 * 1e9, y=0), | ||
variables=Variables(x="total_cus", y="CUTTM"), | ||
budget=Budget( | ||
type="annual_supply_growth", | ||
value=0.5, | ||
), | ||
), | ||
) | ||
|
||
proposer_boost = TLMBoost( | ||
name="Proposer Boost", | ||
actor="Validator", | ||
conditions=[Condition(metric="total_cus", low_threshold=0, high_threshold=2500 * 1e9)], | ||
minting_func=boost_cuttm_f_CUs_nonlinear, | ||
parameters=Parameters( | ||
start=Point(x=250 * 1e9, y=2.5e-9), | ||
end=Point(x=2500 * 1e9, y=0), | ||
variables=Variables(x="total_cus", y="CUTTM"), | ||
budget=Budget( | ||
type="annual_supply_growth", | ||
value=0.25, | ||
), | ||
), | ||
) | ||
|
||
supplier_boost = TLMBoost( | ||
name="Supplier Boost", | ||
actor="Supplier", | ||
conditions=[Condition(metric="total_cus", low_threshold=0, high_threshold=2500 * 1e9)], | ||
minting_func=boost_cuttm_f_CUs_nonlinear, | ||
parameters=Parameters( | ||
start=Point(x=250 * 1e9, y=3.5e-8), | ||
end=Point(x=2500 * 1e9, y=0), | ||
variables=Variables(x="total_cus", y="CUTTM"), | ||
budget=Budget( | ||
type="annual_supply_growth", | ||
value=3.5, | ||
), | ||
), | ||
) | ||
|
||
source_boost_1 = TLMBoost( | ||
name="Sources Boost 1 - CU Based", | ||
actor="Source", | ||
conditions=[Condition(metric="total_cus", low_threshold=0, high_threshold=2500 * 1e9)], | ||
minting_func=boost_cuttm_f_CUs_nonlinear, | ||
parameters=Parameters( | ||
start=Point(x=250 * 1e9, y=7.5e-9), | ||
end=Point(x=2500 * 1e9, y=0), | ||
variables=Variables(x="total_cus", y="CUTTM"), | ||
budget=Budget( | ||
type="annual_supply_growth", | ||
value=0.75, | ||
), | ||
), | ||
) | ||
|
||
|
||
# def boost_prop_f_CUs_sources_custom(tlm_per_service_df: pd.DataFrame, network_macro: dict, params: dict) -> pd.Series: | ||
# """ | ||
# This boost is a proportional cuttm boost on top of sources boost. | ||
# It is intended to reflect the additional per-service boost that is applied | ||
# in the spreadsheet as the "sources boost" made by Shane. | ||
# """ | ||
|
||
# assert params.variables.x == "total_cus" | ||
|
||
# # The modulation of the parameter is linear | ||
# a_param, b_param = math_utils.get_linear_params( | ||
# [params.start.x, params.start.y], | ||
# [params.end.x, params.end.y], | ||
# ) | ||
# max_mint = -1 | ||
# if params.budget.type == "annual_supply_growth": | ||
# # Calculate annualized growth | ||
# max_mint = ((params.budget.value / 100.0) * network_macro["total_supply"]) / (365.2) | ||
# elif params.budget.type == "POKT": | ||
# max_mint = params.budget.value | ||
# else: | ||
# raise ValueError('Budget type "%s" not supported' % params.budget.type) | ||
# param_use = math_utils.calc_linear_param( | ||
# [network_macro[params.variables.x]], | ||
# a_param, | ||
# b_param, | ||
# params.end.x, | ||
# bootstrap_start=params.start.x, | ||
# ) | ||
|
||
# # Calculate (maximum) total minted in each service | ||
# per_service_max = ( | ||
# param_use * network_macro["CUTTM"] * tlm_per_service_df["cu_per_node"] * tlm_per_service_df["active_nodes"] | ||
# ) | ||
# # Apply budget | ||
# if max_mint > 0: | ||
# if max_mint < per_service_max.sum(): | ||
# # Scale values | ||
# per_service_max *= max_mint / per_service_max.sum() | ||
# # Return amount to mint in each service by this boost | ||
# return per_service_max | ||
|
||
|
||
# source_boost_2 = TLMBoost( | ||
# name="Sources Boost 2 - Shane's", | ||
# recipient="Source", | ||
# conditions=[Condition(metric="total_cus", low_threshold=0, high_threshold=1500 * 1e9)], | ||
# minting_func=boost_prop_f_CUs_sources_custom, | ||
# parameters=Parameters( | ||
# start=Point(x=5 * 1e9, y=0.9 * 0.7), | ||
# end=Point(x=1500 * 1e9, y=0.1 * 0.7), | ||
# variables=Variables(x="total_cus", y="CUTTM"), | ||
# budget=Budget( | ||
# type="POKT", | ||
# value=40e3, | ||
# ), | ||
# ), | ||
# ) |
Oops, something went wrong.