Hello everyone,
I have proposed a very exciting root track referendum that will effectively increase the Treasury's revenue by ~43,000 KSM per year. This solution is totally decentralized, autonomous, and, most importantly, can be enacted without needing to issue a system.setCode
call to upgrade to a custom runtime. I can't afford the decision deposit myself, so I'm calling on anyone with enough liquid KSM to place the deposit if you want this to be considered by the ecosystem. Allow me lay it all out:
Simply put, this referendum will do the following:
Here is the call that enlivened the proxies and added the Treasury as a delegate for each one. Here is the call that removed my account as a delegate for each one. Here is the call that confirms that I indeed do not have control of the proxies.
The reason for the proxy configuration is that the Treasury itself can't join multiple nomination pools, so to achieve thorough decentralization we need to utilize proxy accounts that are only controlled by the Treasury. And even if we wanted the Treasury to join just one pool, 270,000 KSM in one pool would yield very inefficient rewards since each validator in the pool would be nominated with way more than the average.
I hand-selected these pools because they are maintained by people and organizations that have a good track record and are clearly here to stay. If a pool starts misbehaving, it will be quite easy to get a referendum passed to unbond from that pool and join another. This selection is the only potentially biased decision made in this process but I hope the ecosystem can trust my judgment - I really tried to be as unbiased as possible.
The amounts are what I believe to be a good balance between liquidity and passive revenue. With the Society funds, the Treasury only needs to offer up about half its free balance to these pools. If the community believes the Treasury needs to be more liquid, we can simply pass a referendum to unbond a certain amount from each pool and transfer the funds back to the Treasury. Remember these funds are not being spent. They are being staked.
Just a quick note, the reason for the 30,001 KSM balance transfers but only 30,000 KSM being joined to a pool is because an account cannot dip below the existential balance while joining a nomination pool. These 9 KSM will be returned to the Treasury when the first reward claim is enacted by the scheduler. I know I enlivened the proxies with existential balances after I made them, but it's best to be redundant.
Finally, the scheduler call is scheduled for Block #17,798,400 because I wanted to make sure that it would get scheduled even if this referendum took the maximum time possible, i.e. 432,000 blocks from the next spend period which starts at block #17,366,400. The maximum time this referendum could take is equal to 5 spend periods, so the Treasury would receive its first RoS sometime around May 6th. Also, the scheduled calls have a priority of 49
to ensure there's enough higher priorities for other scheduled calls and repeats 333 times to ensure automated payouts for the next few years.
Before we get into projections, I want to address a very annoying bug in polkadot.js that probably hurts the ecosystem's marketability. The app uses api.query.auctions.auctionCounter
to calculate the ideal staking proportion in the ecosystem. This is wrong and it's not what the runtime does. By using api.query.auctions.auctionCounter
you're querying the total number of auctions that have ever happened - currently at 76. Since this is greater than the max of 60 parachains allocated 30% of the supply, the app defaults to 60 in its ideal staking calculation. In other words, it takes that whole 30% allocation away from 75% to get an ideal staking proportion of 45%. That's why it shows ~10% RoS because that's what you get when you plug those numbers into the inflation rate formula. If you use the correct number of 43 non-system parachains and account for the 270,000 KSM throwing the total staked proportion off-kilter, you get an RoS closer to 16%. I can perform the math if anyone wants confirmation.
Now that that's out of the way, if we estimate the expected revenue with the ecosystem average return on staking of 16% (rewards not compounding), we get ~118 KSM per day in revenue, or 0.00822 KSM per block on average. Based on my analysis of the Treasury over 1.2 million blocks, the average revenue per block is currently at 0.0166. Therefore:
This referendum will instantly increase the Treasury's revenue by ~50%.
It will be interesting to see what this number actually ends up being if this referendum passes. Needless to say, I think everyone can agree that if this can be done, it definitely should.
This referendum is the first step in a multi-referendum plan to stop the unsustainable decline of the Treasury's balance
The first two steps are actionable and can be executed within the next 30 - 45 days. The 3rd step in this plan is where it gets vague, but that's only because it's far in the future and relies on variables that are out of our control. We would obviously monitor revenue, spending, and KSM price to ensure we are being prudent with Treasury management.
Nomination pools aren't the solution for this, we should instead implement a Treasury staking pallet in the runtime.
The fact of the matter is that this has been a topic of discussion for many months, yet there has been no call to action or any real change in all that time. Here is a solution that works right now and doesn't require a system.setCode
call. If we strike this down, that's just more time the Treasury isn't earning this revenue. Enough pussyfooting, let's get a solution out now even if that solution isn't the best possible one.
I support this solution but I don't agree with the selection of the nomination pools.
Okay, then reconfigure the call and pick 9 different pools. Want more pools? Then create more pure proxies in the same way I did, reconfigure the call, propose your own root
track referendum, and leave it to the token holders to decide.
You don't have to use proxies to do this, there's a better batch of calls, the scheduler call could be better, etc.
Like I said above, just reconfigure the call and submit your own referendum then. This is openGov after all. If you have a better way of doing this, by all means, please show everyone how it's done.
There is a fundamental problem with using fees collected from transactions to secure the network via staking.
This is something I've been pondering - is staking Treasury/ Society funds into the ecosystem a lot like a snake eating its own tail? I've come to the conclusion that no, recirculating "burned" funds back into staking doesn't hurt the security of the network. That's because the funds would otherwise eventually end up getting paid out to independent parties who would sell it on the open market. At the end of the day, these funds will eventually go back into circulation, so best to stake them across a decentralized set of validators.
How do you know that these calls will work?
Please feel free to test these calls yourself by using Chopsticks and follow my testing environment documentation below. You can also verify these calls using different tools, whatever floats your boat. While I am very confident that these calls will work as expected it's always good to get more eyes and minds scrutinizing the technicalities.
Before I could confidently propose this on chain, I had to make sure that every call worked exactly as intended.I decided to utilize Chopsticks because it seemed to be the easiest way to test exactly how Kusama works. I'm sure there are far more efficient ways of setting up a dev environment that can test Kusama, especially ones that don't require the workarounds I had to utilize, but I was shooting for convenience and speed. Since Kusama doesn't have a Sudo
pallet and I couldn't figure out how to hardcode an account with root origin in the config.yml file, I had to be clever. In the process of finding workarounds I came to the important realization that confirmed referenda on Kusama are nothing more than scheduled calls in the scheduler
. That means if I could hardcode the scheduler.agenda
in the Chopsticks config, I could simulate any successful referenda on Kusama. I needed to test the following:
root
submit a balances.forceTransfer
to move Society funds to the Treasury?root
submit a utility.dispatchAs(signed,call)
on behalf of the Treasury?root
submit a proxy.proxy
via utility.dispatchAs(signed,call)
on behalf of the Treasury?I obviously wouldn't have submitted this referendum on chain if any of these things weren't possible. Turns out root
is really, really powerful! To test these things I had to hard code proxies, scheduled calls, preimages, and nomination pool rewards. I first focused on proxy configuration and joining nomination pools by adding the following under import-storage
in the default kusama.yml
file in Chopsticks:
Proxy:
Proxies:
-
- [G8dY4RCzMW85s55GjubvUBQEGFqri7Y6BB3HhJN3QF6NYHS]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
-
- [Df9BxuggXYdszox1CHHgt8SqdziJXYDcY4ow72bGbyfx5YP]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
-
- [JAhvx2YRj9Rc1u9ke7W8mjWwosDmYpkVrj3CMsbJXaoGEAh]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
-
- [DFwZEF8rNEsZx8tzfGZHuM8Pma5RV1qQEZy7urDk3QcWKss]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
-
- [D5vJYsuWZ9vPn5wLk7zfQb9GiqcL3CEhzyLt3qForGACQ7s]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
-
- [E51bb6z5DZTzDomkG8QMXLCfATgYvwqovA2WUJdEZpA8YpY]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
-
- [Hvn4qnbRc17moQjwRTSVwzGGFFDY73uVKGgdwKi15zvibM8]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
-
- [J9Wv965oJqTRT8mMJkcrkBdSXt3hUSaP4mmnnYBnUqjGU6z]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
-
- [DgBokRc1ZTvdCS3AmMikpZkWDoK6CwtTaUjp8t1Y6ZS2dNF]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
Preimage:
PreimageFor:
-
-
- ['0x59738bdd0aeb9fd2bed0db1e22f13e90afa1b478fc7d07a8aa3a35b9b5ffefb4', 1704]
- '0x18040c0402006d6f646c70792f736f6369650000000000000000000000000000000000000000006d6f646c70792f747273727900000000000000000000000000000000000000001300000c3d5d53aa01180300016d6f646c70792f747273727900000000000000000000000000000000000000001804480400009d5935861195dfc92a0e61ecfb09cc6016acbd90b16e8db292ca9a92d6cfcc570f0010e823c0956a0400002fe9b18c2e4a19356409e553f9947cad1bb7dec2e0b03c7ee582443fd6ca156f0f0010e823c0956a040000f766f5e3e988404ae8e9006d4ffe8ade3727afeacc9691f6e51b2bf5620997260f0010e823c0956a0400001e37e3485870efbc43f017d710703c8273d0ddf708b0943c391dd931c9162b170f0010e823c0956a0400001693372d0721cf86bd276aac99ff208d00f02c08ff5aede6b1fcbea4e4d190c00f0010e823c0956a040000421e06239e41944ace1955b5a2782c9b77a2ff2faad1cef446073de06a928da50f0010e823c0956a040000ecc772b808e917a470b8b7ef253a2e54baaac41f0315e8fdb0227955333e20f00f0010e823c0956a040000f67ea38a89e5243c11196daac805636e79f2c28221ae7a72a7d390b161b9f4120f0010e823c0956a04000030b5bf9cb181c2123093dcbb88ee3382725f496ab37267001c7de8145d3edb400f0010e823c0956a1e00009d5935861195dfc92a0e61ecfb09cc6016acbd90b16e8db292ca9a92d6cfcc570029000f0000434fd7946a010000001e00002fe9b18c2e4a19356409e553f9947cad1bb7dec2e0b03c7ee582443fd6ca156f0029000f0000434fd7946a020000001e0000f766f5e3e988404ae8e9006d4ffe8ade3727afeacc9691f6e51b2bf5620997260029000f0000434fd7946a040000001e00001e37e3485870efbc43f017d710703c8273d0ddf708b0943c391dd931c9162b170029000f0000434fd7946a080000001e00001693372d0721cf86bd276aac99ff208d00f02c08ff5aede6b1fcbea4e4d190c00029000f0000434fd7946a0c0000001e0000421e06239e41944ace1955b5a2782c9b77a2ff2faad1cef446073de06a928da50029000f0000434fd7946a120000001e0000ecc772b808e917a470b8b7ef253a2e54baaac41f0315e8fdb0227955333e20f00029000f0000434fd7946a360000001e0000f67ea38a89e5243c11196daac805636e79f2c28221ae7a72a7d390b161b9f4120029000f0000434fd7946a4b0000001e000030b5bf9cb181c2123093dcbb88ee3382725f496ab37267001c7de8145d3edb400029000f0000434fd7946a560000001d0080a00b0101805101004d01000000180300016d6f646c70792f747273727900000000000000000000000000000000000000001804241e00009d5935861195dfc92a0e61ecfb09cc6016acbd90b16e8db292ca9a92d6cfcc570018040829020404006d6f646c70792f74727372790000000000000000000000000000000000000000011e00002fe9b18c2e4a19356409e553f9947cad1bb7dec2e0b03c7ee582443fd6ca156f0018040829020404006d6f646c70792f74727372790000000000000000000000000000000000000000011e0000f766f5e3e988404ae8e9006d4ffe8ade3727afeacc9691f6e51b2bf5620997260018040829020404006d6f646c70792f74727372790000000000000000000000000000000000000000011e00001e37e3485870efbc43f017d710703c8273d0ddf708b0943c391dd931c9162b170018040829020404006d6f646c70792f74727372790000000000000000000000000000000000000000011e00001693372d0721cf86bd276aac99ff208d00f02c08ff5aede6b1fcbea4e4d190c00018040829020404006d6f646c70792f74727372790000000000000000000000000000000000000000011e0000421e06239e41944ace1955b5a2782c9b77a2ff2faad1cef446073de06a928da50018040829020404006d6f646c70792f74727372790000000000000000000000000000000000000000011e0000ecc772b808e917a470b8b7ef253a2e54baaac41f0315e8fdb0227955333e20f00018040829020404006d6f646c70792f74727372790000000000000000000000000000000000000000011e0000f67ea38a89e5243c11196daac805636e79f2c28221ae7a72a7d390b161b9f4120018040829020404006d6f646c70792f74727372790000000000000000000000000000000000000000011e000030b5bf9cb181c2123093dcbb88ee3382725f496ab37267001c7de8145d3edb400018040829020404006d6f646c70792f7472737279000000000000000000000000000000000000000001'
StatusFor:
-
- ['0x59738bdd0aeb9fd2bed0db1e22f13e90afa1b478fc7d07a8aa3a35b9b5ffefb4']
- Unrequested:
deposit:
- 5FEejaLgafnvB64mmXnw4o7P4PsuWhpPpgw8neeVB5fj4j7P
- 1392266606400
len: 1704
Scheduler:
Agenda:
-
- [17202800]
-
- maybeId: null
priority: 0
call:
Lookup:
_alias:
hash_: hash
hash_: '0x59738bdd0aeb9fd2bed0db1e22f13e90afa1b478fc7d07a8aa3a35b9b5ffefb4'
len: 1704
maybePeriodic: null
origin:
system: Root
I then forked Kusama by running yarn start dev --config=configs/kusama.yml --block=17202799
You may notice that the block I decided to fork is exactly one block before the hard-coded scheduled task. That's because Chopsticks only writes a new block when you submit an extrinsic. So all I needed to do to test this call was to submit a system.remark
. By doing so, the Treasury successfully transferred 30,001 KSM to each pure proxy and joined 9 distinct pools via the scheduler. The pools remained open and the protocol also scheduled the desired reward claim.
Just a note: the scheduler automatically requests its own calls' preimages so there is no need to explicitly store the preimage needed to claim pool rewards.
I then tested whether the claimPayout
+ transferAll
would work. I had some trouble hard coding the nomination pool to accommodate the massive claim, but got it figured out by adding the following to the default kusama.yml
in Chopsticks:
Proxy:
Proxies:
-
- [G8dY4RCzMW85s55GjubvUBQEGFqri7Y6BB3HhJN3QF6NYHS]
-
-
- delegate: F3opxRbN5ZbjJNU511Kj2TLuzFcDq9BGduA9TgiECafpg29
proxyType: Any
delay: 0
- 668033331300
Preimage:
PreimageFor:
-
-
- ['0x6d4c5902a1a43810dfe33fa7c1e142392068c6af51f6788363173723b2c31712', 113]
- '0x180300016d6f646c70792f747273727900000000000000000000000000000000000000001e00009d5935861195dfc92a0e61ecfb09cc6016acbd90b16e8db292ca9a92d6cfcc570018040829020404006d6f646c70792f7472737279000000000000000000000000000000000000000001'
StatusFor:
-
- ['0x6d4c5902a1a43810dfe33fa7c1e142392068c6af51f6788363173723b2c31712']
- Unrequested:
deposit:
- 5FEejaLgafnvB64mmXnw4o7P4PsuWhpPpgw8neeVB5fj4j7P
- 1339233326100
len: 113
Scheduler:
Agenda:
-
- [17202800]
-
- maybeId: null
priority: 0
call:
Lookup:
_alias:
hash_: hash
hash_: '0x6d4c5902a1a43810dfe33fa7c1e142392068c6af51f6788363173723b2c31712'
len: 113
maybePeriodic: null
origin:
system: Root
NominationPools:
BondedPools:
-
- [1]
- points: '30000000000000000'
state: Open
memberCounter: 66
roles:
depositor: E8a4iJyDLd2ZysHt4bWfg5VG3RwNfHqSZtkyt5SPNJpmYoq
root: E8a4iJyDLd2ZysHt4bWfg5VG3RwNfHqSZtkyt5SPNJpmYoq
nominator: Fc51t7QUm5sPhx6gJdxzVBjznqqoRyp2gHTJSnbRBcLExAo
stateToggler: GF5PrXFcW7YDKKKfgJsMJE9xKF1UgE64kVSWYxNNo7waZYe
RewardPools:
-
- [1]
- lastRecordedRewardCounter: '10000000000000000'
lastRecordedTotalPayouts: '5000000000000000'
totalRewardsClaimed: '2500000000000000'
PoolMembers:
-
- [G8dY4RCzMW85s55GjubvUBQEGFqri7Y6BB3HhJN3QF6NYHS]
- poolId: 1
points: '30000000000000000'
lastRecordedRewardCounter: 0
unbondingEras: {}
System:
Account:
-
-
- 5FEejaLgafnvB64mmXnw4o7P4PsuWhpPpgw8neeVB5fj4j7P
- data:
free: '10000000000000000000'
-
-
- G8dY4RCzMW85s55GjubvUBQEGFqri7Y6BB3HhJN3QF6NYHS
- data:
free: '1000000000000'
-
-
- F3opxRbN5ZavB4LTn2FZim9tPCHyvapGAAZzdDp5pzfg3sy #stash
- data:
free: '30000000000000000'
-
-
- F3opxRbN5ZavB4LTn2XJkJjzssVSUggzq75YZueYesPwk5J #reward
- data:
free: '30000000000000000'
I tested this with the same process as above. The reward was claimed successfully and transferred to the Treasury as expected. I only needed to prove the concept with one proxy since we can simply batch all the others.
With that, I confirmed that everything I hypothesized was absolutely possible on Kusama.
This referendum will configure 9 pure proxies controlled only by the Treasury to stake a total of 270,000 KSM across 9 nomination pools on behalf of the Treasury and pay out rewards to the Treasury every 6 days starting ~May 6th. Out of the 270,000 KSM, 120,000 KSM comes from the Society and 150,000 KSM comes from the Treasury.
By staking these funds, we expect a projected revenue increase of ~43,000 KSM per year, which is approximately a 50% increase from what the Treasury is earning now.
Threshold