Proposal - Referendum #12: Adjust tokenomics params to reflect difference in block time

I would like to propose adjustment in tokenomics params to reduce impact of gap between real and target block time.

Target time on parachains is 12s.
Those are our avg block times calculated based on onchain data.

Average block time in last  1 day     16.4 s
Average block time in last  1 week    15.7 s
Average block time in last  2 weeks   15.5 s
Average block time in last  1 month   16.1 s
Average block time in last  2 month   15.7 s

As you can see we have long term 30% gap. It impacts all features which base on block number (not timestamp).
For example mining rewards are block based - which directly impact APR of owners and stakers. It is worth noting that in app.phala.network all values you see are also block based.
If you calculate your APR time based you will see it differs for 30%

Worth noting (mentioned by team):
This issue occurs because substrate has limited (obvious) throughput in processing blocks and simultaneously Phala extremely utilize onchain actions.

Compare Moonriver and Khala below (at most it is even 100x more transactions).
Btw. Moonriver is second most used chain ;)

As you can see lot of things happens on Khala and it is probably not possible to improve throughput in short term.

However this proposal is to reduce impact of that issue.
IMO block time in any contract calculations should not be fixed to target 12s value.
I think we should periodically adjust that value to reflect real block time.
Depending how much it will vary we should adjust it monthly based on last month average block time.

3 Likes

It seems to me this could be calculated for each mining period (presently 1 week). We could easily calculate the number of “missing blocks” and provide a shrinking subsidy as an incentive to early miners/stakers/delegators. Obviously, many calculations will happen at the period boundaries to check miners joining, stakes exiting, etc. This should be added to those calculations until (1) Khala/Phala networks are truly running at 12s averages, (2) the chain no longer seems financially viable/isn’t adopted at the rate we all know it should be.

~ aka Hologram

2 Likes

I understand you agree with proposal. But I would like to clarify that this can’t be treated as “as an incentive to early miners/stakers/delegators”.
Because this is not any additional reward to participants. Those are not over planned values.
This proposal should prevent current state in which we are rewards under planed values.
I wanted this to be clear :slight_smile:

2 Likes

Yes, as originally designed in the tokenomic paper, the current mining subsidy should work when the block time matches 12s exactly. Now given the actual block time is between 13-16s, it’s reasonable to offset the subsidy to match the original release schedule.

image

The tokenomic is executed by the Gatekeepers, and Gatekeepers read the parameters defined on the blockchain at phalaMining.tokenmoicParameters(). It’s possible to update the parameter by a referendum.

Steps:

  1. Dump the current Khala tokenomic parameters
  2. Adjust the block subsidy
  3. Generate the update_tokenomic call with the new parameter

To dump the current tokenomic parameters, you will need to clone phala-blockchain codebase, and run:

cd scripts/js
yarn
node src/console.js chain get-tokenomic

(wip: adjust and generate democracy proposal call)

1 Like

Dump output

  phaRate: '0.82999999999999999998',
  rho: '1.000000666600231',
  budgetPerBlock: '6.2499999999999999998',
  vMax: '30000',
  costK: '0.000000019054528616676159186',
  costB: '0.00004061623205149357237',
  slashRate: '0',
  treasuryRatio: '0.19999999999999999999',
  heartbeatWindow: '20',
  rigK: '0.36144578313253012048',
  rigB: '0',
  re: '1.5',
  k: '50',
  kappa: '1'
}

Based on current block times:

[AnalyzeCommand] Average block time in last  1 day   22.1 s
[AnalyzeCommand] Average block time in last  1 week   17.5 s
[AnalyzeCommand] Average block time in last  2 weeks   16.7 s
[AnalyzeCommand] Average block time in last  1 month   16.2 s
[AnalyzeCommand] Average block time in last  2 month   16.1 s

I think it is reasonable to pick monthly avg (considering referendum limitations)
So it is 16.2s which gives ratio (16.2 / 12) = 1.35 => +35% adjustment

I adjusted budgetPerBlock by adding 35%
So now it will be 8.4375

  phaRate: '0.82999999999999999998',
  rho: '1.000000666600231',
  budgetPerBlock: '8.4375',
  vMax: '30000',
  costK: '0.000000019054528616676159186',
  costB: '0.00004061623205149357237',
  slashRate: '0',
  treasuryRatio: '0.19999999999999999999',
  heartbeatWindow: '20',
  rigK: '0.36144578313253012048',
  rigB: '0',
  re: '1.5',
  k: '50',
  kappa: '1'
}

Which generates call:

0x5d03045705e17a14ae47e17ad40000000000000000fd7eb4062f0b000001000000000000000000000000000070080000000000000000000000000000003075000000000000a5ffacd6510000000000000000000000cdc46a636da90200000000000000000000000000000000000000000000000000333333333333333300000000000000001400000025bcd1d4f9b5875c000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000320000000000000000000000000000000100000000000000

I understand it is only about to submitting referendum here

I’m waiting for possible suggestions / confirmations.

1 Like

Yes, it makes sense generally. However I’d also suggest to update the PHA price to reflect the latest price changes.

From the original rust code, there are four parameters calculated based on the PHA rate:

let cost_k = fp!(0.0415625) * block_sec / year_sec / pha_rate; // annual 0.0415625, convert to per-block
let cost_b = fp!(88.59375) * block_sec / year_sec / pha_rate; // annual 88.59375, convert to per-block
// -- snip --
let rig_k = fp!(0.3) / pha_rate;
let rig_b = fp!(0) / pha_rate;

The price of PHA can be the monthly avg from CMC, thus $0.667:

image

Here’s the js code I used to generate the new parameters:

let pha_rate = 0.667;

let block_sec = 12;
let hour_sec = 3600;
let day_sec = 24 * hour_sec;
let year_sec = 365 * day_sec;

let cost_k = 0.0415625 * block_sec / year_sec / pha_rate;
let cost_b = 88.59375 * block_sec / year_sec / pha_rate;
            
let rig_k = 0.3 / pha_rate;
let rig_b = 0 / pha_rate;

console.log({cost_k, cost_b, rig_k, rig_b});

Output:

{
  cost_k: 2.3711032611548103e-8,
  cost_b: 0.00005054193793514202,
  rig_k: 0.44977511244377805,
  rig_b: 0
}

If we put them together, here’s the final tokenomic json:

{
  phaRate: '0.667',
  rho: '1.000000666600231',
  budgetPerBlock: '8.4375',
  vMax: '30000',
  costK: '0.000000023711032611548103',
  costB: '0.00005054193793514202',
  slashRate: '0',
  treasuryRatio: '0.19999999999999999999',
  heartbeatWindow: '20',
  rigK: '0.44977511244377805',
  rigB: '0',
  re: '1.5',
  k: '50',
  kappa: '1'
}
2 Likes

With the above information you can create the encoded proposal (a call). However, instead of using “Democracy > Submit Preimage”, you should send a manual transaction from “Developer > Extrinsics”.

Choose Democracy.notePreimage() to submit the proposal:

image

Then you can get the hash of the call (i.e. the proposal hash) from Subscan, in the event section of your transaction. Then you can submit a proposal via “Democracy > Submit Proposal” with the hash you got.

2 Likes

Ok thank you for clarification!

So final tokenomic params are:

{
    "phaRate": "0.667",
    "rho": "1.000000666600231",
    "budgetPerBlock": "8.4375",
    "vMax": "30000",
    "costK": "0.000000023711032611548103",
    "costB": "0.00005054193793514202",
    "slashRate": "0",
    "treasuryRatio": "0.19999999999999999999",
    "heartbeatWindow": "20",
    "rigK": "0.44977511244377805",
    "rigB": "0",
    "re": "1.5",
    "k": "50",
    "kappa": "1"
}

This is call for it:

0x5d03045705508d976e1283c0aa0000000000000000fd7eb4062f0b000001000000000000000000000000000070080000000000000000000000000000003075000000000000255a8ed66500000000000000000000009d3473f8f34f030000000000000000000000000000000000000000000000000033333333333333330000000000000000140000003b1c318036762473000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000320000000000000000000000000000000100000000000000

My Democracy.notePreimage()
Subscan

With proposal hash:

0x3fb8adf8a43d49fefa480749bfba3a70c12ee707a2c0c7b171a842e5ee6d1b7d

Here you have Democracy.propose
Subscan

1 Like

Nice. Would you also write a bit on SubSquare (the diamond icon on the right side of the proposal)? Only you have the permission to edit the proposal content. A link to this post would be nice.

1 Like

Sure, done!
https://khala.subsquare.io/democracy/proposal/8

2 Likes

Make sense, I will support this idea.

2 Likes

I just found a problem when generating the proposal preimage. I used call.toHex() to get the call data. However it turned out not a “raw” encoded call. It has some prefix added by polkadot.js. As a result, the prefixed call will not be recognized by the blockchain.

Now if you check the democracy page, it still shows an “Add Preimage” button, because under the hood the sdk tries to decode a raw call, rather than a prefixed call.

Here’s the prefixed call:

0x5d03045705508d976e1283c0aa0000000000000000fd7eb4062f0b000001000000000000000000000000000070080000000000000000000000000000003075000000000000255a8ed66500000000000000000000009d3473f8f34f030000000000000000000000000000000000000000000000000033333333333333330000000000000000140000003b1c318036762473000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000320000000000000000000000000000000100000000000000

By removing the prefix, we get the raw call:

0x5705508d976e1283c0aa0000000000000000fd7eb4062f0b000001000000000000000000000000000070080000000000000000000000000000003075000000000000255a8ed66500000000000000000000009d3473f8f34f030000000000000000000000000000000000000000000000000033333333333333330000000000000000140000003b1c318036762473000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000000320000000000000000000000000000000100000000000000

And we can get the correct call hash. Note even if you paste the prefixed version in “Decode Extrinsic” tool on Polkadot.js, you still get the correct hash as below. However if we submit the prefixed call to “notePreimage()”, we will get the hash of prefixed call (invalid), and thus doesn’t match the one as below:

0x1e6f17118958e5149fc6ac0a294f9c746fee4fa36364ed1c3031dfeb3680e94b

Here’s the pull request to fix the update-tokenomic tool: console.js: generate raw call for update-tokenomic by h4x3rotab · Pull Request #589 · Phala-Network/phala-blockchain · GitHub

Solution: We should create another proposal to replace the current one, and get more seconds than the current proposal to get proceed to the referendum. We have to do it as soon as possible since it’s just hours to the next voting period.

1 Like

New proposal submitted

1 Like

Yeap that is interesting.
Thx for describing it.