The idea of deprecating controllers for proxies has been around for a while, with the issue being posted 2 years ago now.
The benefits of doing this include:
- Removing duplicated logic in the codebase (controllers do a lot of what proxies can do)
- No longer need to call
Bonded
storage to get the controller/stash mapping - Simplify the staking pallet and further streamline it in prep for refactoring
Calls from proxies however do require an additional storage read.
From an end user perspective, less emphasis will need to be put on the stash account. Beyond the initial bond()
transaction, proxies can manage the position (including unbond) alone. Where we currently try to give equal footing to stash and controller in UIs, this will no longer be necessary. The proxy will be the sole account of interest.
The main issue of not implementing proxies now (please post more if missing):
- All nominators need a proxy, and proxies require a ~20 DOT deposit.
- Migration strategy from controllers → proxies needs to be finalised.
Current solution of interest: Provide free proxies to nominators.
ProxyProvider
@kianenigma has posted a solution of having a ProxyProvider
for the staking pallet, where a proxy implementation can be used to create / manage staking proxies.
trait ProxyProvider {
type AccountId;
// get the proxy of stash, if any.
fn proxy_for(stash: &Self::AccountId) -> Option<Self::AccountId>;
fn create_proxy(...) -> Result<_, _>;
fn remove_proxy(...) -> Result<_, _>;
}
// As a first step, staking's inner controller management system will be the `ProxyProvider`
impl ProxyProvider for pallet_staking::Pallet<_> { ... }
EligibleFreeProxy hook
Another option would be the other way round, letting proxy
pallet know about the concept of free deposits, rather than the staking
pallet know about proxies.
A hook can provide accounts that are eligible to bypass proxy deposits, with a function like eligible_for_staking_proxy(who) -> bool
would be implemented in the staking pallet. An already bonded staker could then bypass the deposit, and wouldn’t require tight / loose coupling.
trait EligibleFreeProxy {
type AccountId;
fn get_eligible_staking(who: AccountId) -> bool;
fn get_eligible_pure(who: AccountId) -> bool;
...
}
// and implement in staking
impl EligibleFreeProxy {
fn get_eligible_staking(who: AccountId) -> {
// storage read x 2
bonded && !hasProxy ? true : false
}
}
In the interest of future staking refactors, I feel now is a good time to address this in our attempt to further streamline staking.
The goal of this thread would be to get validation of a solid strategy we can take forward and implement.