Proposal for Introducing Governance Lock to Poolv1 contract

A Proposal for Introducing Governance Lock to Poolv1 contract

The purpose of starting this thread is not so much to present a proposal as-is, but more to detail a problem and raise a possible solution for community discussion. For clarity, this is also NOT an HSP or a proposal for one, although it may or may not take that form in the future.

The solution I’ll propose here is probably not the only solution, others might have other thoughts. Still, it’s the most elegant solution I could personally come up with, and I think this is an important topic- probably THE most important topic- for HoS to tackle if it’s to have any chance of longer term success.

Background & Problem Statement

Currently, the House of Stake contract operates in more-or-less the following way:

  • User w/ liquid NEAR or common LST tokens (LiNEAR, stNEAR, rNEAR) wants to vote in House of Stake and/or get governance rewards etc
  • User goes to HoS website and interacts with interface
  • User’s account registers with veNEAR token contract
  • User’s account deploys lockup from veNEAR contract (and register name)
  • User’s account moves NEAR/LST* to lockup account
  • Lockup account locks NEAR on it’s balance, minting veNEAR to user’s main account
  • stake locked NEAR in lockup contract to pool contract

(*this is not recommended, because LSTs cannot be withdrawn, raising the question of why this function exists at all)

There are a number of issues with this structure imo, but the biggest problem with the structure as it exists is that users with native staked NEAR cannot participate without unstaking from their existing staking positions on standard whitelisted poolv1 contracts.

For many users, moving NEAR out of a staking pool presents major headaches. These are often a holder’s larger positions and therefore more likely to be secured/difficult to access, so there is some justified reluctance to move that NEAR, let alone put all of it into the system above; and that’s before we consider possible tax consequences.

Furthermore, if we consider that ~47% of all NEAR is native staked and that NEAR staked in this fashion is likely the most common holding for those who hold NEAR long term, this is also undoubtedly the largest constituency of potential governance participants.

However, simply building functionality to allow currently staked NEAR to participate cannot work given the current parameters of the poolv1 contract. The reason for this is that the staking pool contract treats the delegator’s rights to withdraw as sacred, and even if we built functionality to externally check the user’s staked balance and mint veNEAR, we cannot prevent the user from withdrawing, making a lock-up impossible. See here: core-contracts/staking-pool at master · near/core-contracts · GitHub

Therefore, in order to have native staked users participate in veNEAR, there are two solutions I can see:

  • one, build a tool that causes a given account to remove access keys (incl. full), deploys a new contract to that account, and essentially makes the native staking user’s account into a multisig or
  • two, implement a protocol-wide update to the standard pool contract enabling delegates to the pool contract to choose to lock their staked NEAR.

I think #2 is the better solution, and I’ll explain why.

TL;DR: HoS contracts are janky right now (imo) and native stakers cannot participate. I want to upgrade the standard staking-pool contract.

Rationale

I can understand feeling iffy about this. For one thing, the standard staking-pool contract secures 527.9 million NEAR(!), and hasn’t been touched in 6 years(!). So upgrading it may seem a pretty big, kinda risky move.

However, I think this makes sense to do for a variety of reasons, both practical and philosophical.

Part of the reason for staking pools, and of proof of stake at the higher level, is to “secure the network” by having the total weight of the stake “decide” the canonical network. This is the basic, no-frills “governance” of any proof-of-stake chain, existing at the most fundamental level. The core contracts even make this arguably explicit by including a “voting” contract whose function allows the pool owner to “vote” on behalf of their staking pool.

But as we learned from the emissions reduction proposal, not every validator wants to participate in governance of the chain. In fact, a sizable plurality of node runners want to remain extremely neutral on protocol changes.

Upgrading the pool contract allows us to circumvent this cleanly and canonically by separating the responsibility for decentralized governance from the responsibility of network security. It also codifies stakeholder governance explicitly at the protocol level.

It’s also considerably better UX than what HoS has now. Already staked your NEAR? Put a lock on it and you’re all set to mint veNEAR to vote on governance and/or get extra rewards.

Finally, I think this would make it fairly lightweight/convenient to incorporate into any interface that’s already indexing pool contracts for managing account staking (wallets, mostly). I think added visibility this way could really contribute to helping grow participation levels, as it may be more passive holders could discover NEAR governance this way as opposed to standard marketing streams.

Solution

Now, I am not a battle-hardened NEAR contract developer, so details here may not be entirely correct. Bear with me if I make any architectural mistakes and please correct me if any of this doesn’t work:

The changes to the staking-pool contract I’m imagining are relatively straightforward:

  1. Add a “stake-lock” function to the staking pool contract. Delegator passes args for amount of stake to lock (max being their total stake) and the duration. This does not change the stake shares amount.
  2. Add a “stake-unlock” function, which sets “unlocking=true” until a future date defined by the lock duration at which point it sets “stake_locked” to 0
  3. Add restrictions to the “unstake” function that prevent the user from unstaking more than “stake” - “stake_locked” unless unlock timer is 0
  4. Add a “view-lock” function so that users and other contracts can easily check the amounts and durations of the lock for each user, as well as whether the account’s unlock function has been triggered or not

You’ll notice none of these functions make any presumptions about veNEAR, which is intentional to preserve future versatility.

Still this would also allow the veNEAR contract to mint/adjust veNEAR balances for accounts based on their stake locked, lock duration, and unlock status via viewing the staking pools the user specifies.

Although, I am not actually sure how lightweight it is to check whether or not a user has unlocked, which may in some cases cause a user to have “ghost veNEAR” while unlocking until the contract next checks their pool lock. Thoughts welcome here.

Implementation

Open to debate on this, but my gut sense is that this is not really a proposal for HoS, but moreso for the Protocol working group (eg. this would probably take the form of a NEP).

If we do want to go this direction, I would want to at least see support among the community here and particularly among the class of respected NEAR developers (Bowen, Eugene, Frol, Slime, etc).

If we discuss this and decide it’s a good approach, I’m happy to work on pushing this forward personally. Interested to get people’s thoughts, thanks much for the read.

6 Likes

Upgrading is kind of a big deal, so I’d like to hear from the holders themselves to validate whether it’s worth it.

Here are some costs associated with this solution:

  • Development of the new smart contract (or edit the current contract, which is written with very old libraries, but might be worth it to save money on audit and development)
  • Security audit, ideally 3-4 audits since this contract is very very very important
  • Implement a protocol feature that allows overriding locked contracts. This might also be useful to update contracts such as wrap.near, which are way too old and don’t follow modern standards, so this will probably have to be done at some point regardless of this proposal
  • Make a protocol upgrade unlocking all the poolv1.near pools
  • Repeat points 1-2 with .pool.near contract (it’s much more complex since it has farms and it’s liquid, so we can’t just apply the same fix)
  • Either force-upgrade all .pool.near pools with a protocol upgrade, or ask pool owners to do that (would be a headache for validators to do, but majority will probably do that if asked)

We’re looking at months of effort to simplify “3 clicks + 24 hour wait”, as a developer I would think it’s stupid, but for institutions it might trigger taxable events etc. I think it’s worth making a survey / analysis of whale wallets to see how many people are actually blocked by this AND would participate in governance if unblocked, vs people not interested in governance at all, and possibly using unstaking as an excuse. After all, that unstake gives them over 2% APY in incentives, and $NEAR price being down probably brings taxes down, makes it a bit hard to believe that ~90% of current stake are blocked only by this. But generally I’m not against this, as long as enough people “promise” to participate in house of stake when this is done, to make the effort is worth it.

Regarding architecture, I think it might be better to just add a “transfer_stake“ function that people can use to transfer stake from their own wallet to their HoS lockup wallet, although might (or might not) require some changes to the lockup contract and not sure how easy it is to upgrade the lockup contract.

5 Likes

This could be an elegant solution. We should be meeting users where they are: in their wallets. I can check with Agora on Monday about the feasibility of adding a “transfer_stake” function to the lockup contract.

5 Likes

Thanks for the replies both!

I did consider proposing alternative means of moving one’s existing stake. The thing that concerns me about introducing such a function is that it strikes me as a potential attack vector. Part of what makes it easy to feel confident and secure with the pool contract is that nothing can happen to your stake: you can put in your NEAR, you can take out your NEAR, but it can’t be moved to any address other than the one that put it in.

Keeping the simplicity this way (only the same address as put in can take out, or choose to introduce a lock which has no functionality other than locking) to my mind keeps things very simple and doesn’t introduce potential avenues for exploitation. As someone who does stake NEAR, I would prefer to keep it this way.

I do think that maybe a larger protocol upgrade with some kind of highly secure means of updating locked contracts (or maybe introducing something between “upgradable” and “locked”) could be useful, but would want NEAR One to weigh in here. Definitely feels like requiring a protocol-wide change to change a contract is a very secure place to be, though.

This will get a bit off topic, but we’ve discussed this within the team a lot, of course. My personal opinion is that (incl all below) on this point, people are not going to be entirely honest. Many people will of course answer “no, this isn’t the issue, the issue is that HoS isn’t doing anything I care about / I don’t want to participate in governance / I don’t conceptually like governance at all”.

But, imo, that’s only true as long as HoS participation is an easy thing to not think about as a large tokenholder. Right now, not many decisions are being made, few changes to the protocol, and little or no treasury is being spent. Doing nothing and collecting APY is a very comfortable place to be. It’s much less comfortable if the chain you’re holding a large stake in suddenly has large holders trying to make consequential decisions, which in turn obviously impact your large holdings as well. At that point, being a passive holder is not as comfortable, and you will want to represent your interests and opinions.

You can already see this starting to happen, obviously- look no farther than the MPC proposal.

My bottom line is this: I don’t personally believe that the existence of chain governance is comfortable. It’s way easier to chill and know that no consequential decisions can be made because no other holders can make them. What we have right now is a state of rational deterrance between stakeholders/validators. But a lack of framework poses a huge roadblock when you reach impasses where only the stake can reasonably ratify protocol changes that need to happen for everyone’s benefit.

But once everyone’s already there… it’s a different question. A “hard no” becomes a “well, maybe” faster than you think, at which point the awkward, potentially tax-consequential process we have now is definitely going to push those “maybes” into “forget it”.

So my take is that reducing friction is far and away the most impactful thing we can do right now, whether or not anyone is going to tell you so. And that’s basically what’s prompting this proposal. Just my 2c!

And thanks again for the replies :slight_smile:

3 Likes

Maybe there could be some kind of “receiver whitelist” so funds can only be transferred to HoS lockup wallets, or even better, “trasnfer_to_lockup“ method that dynamically gets the address of your lockup wallet and not anyone else’s lockup wallet. I like this transfer solution mainly for how simple it would be to implement, not much effort will be needed from implementors or auditors, and much easier to keep it bug-free than a lockup contract which already has its own lockup period of 4 epochs, and will be having another lockup “layer”, and then it will probably not be possible to transfer stake to a different validator, like how it can be done now with lockup wallets.

3 Likes

YES. I agree with the problem and that a solution is needed if we want to increase HoS participation and thus legitimacy.

I also appreciate the discussion and proposed solutions so far.

This is out of scope for me, as I believe it creates too many risks/uncertainties.

I like the second proposed solution more, but both of you brought great counterarguments to that yourself (@bearmans and @slimedrgn ) regarding the risks of making transfers or adding more “locking” layers to pool1.near contracts. Plus, messing with a legacy system that has so much to lose.

What if we would consider a third option?

I don’t know all the details here, but, afaik, pool.near staking/delegating contracts already address many of these hurdles and would be more flexible for allowing the things we want. So, I would rather focus on improving pool.near instead of messing with pool1.near, especially considering this would be an extremely sensitive development for the amount of NEAR currently staked using this legacy system.

If we improve pool.near even more, as it is (afaik) built for being more flexible to these use cases, and, once the framework is ready, start some educational efforts to help validators (who want that) to migrate to a pool.near contract somehow and educate the holders who want to participate in governance (or other interesting use cases that could surge) to delegate to validators running pool.near contracts instead of the legacy pool1.near.

In a first moment, validators could just bootstrap a different node using the pool.near contracts, test and verify the implementation themselves and gradually migrate the stake to the new pool while educating and asking delegators to do the same thing.

It does add some friction and is a much slower solution, but at least we wouldn’t be messing with a sensitive system (that could find some community/validator backlash due to uncertainty, potentially affecting NEAR) and we would be using.

Just my 2 cents. Would like to hear back from you.

2 Likes

Good solution, but it doesn’t solve anything. The main friction is that unstaking and staking in a different way involves 3 transactions and 1 day of wait. Making people switch to pool.near introduces the same issue. Pool.near will soon allow transfer of staked NEAR while still staked (effectively making it an LST), so people can already move to pool.near if they want, and pool.near will soon have all the necessary tech to make a smooth transition happen. Transition from poolv1.near to pool.near will not be smooth though.

2 Likes