Hey y’all.
I’d like to introduce for public scrutiny our idea for an MEV Smoothing Pool for Solo Stakers.
1. What is an MEV Smoothing Pool?
A Smart Contract that receives MEV rewards from a group of stakers that decide to share MEV rewards.
The idea behind it is that one will get a high value MEV block only very seldomly or never. By joining forces with other stakers, the overall rewards for everyone increase.
Does it make sense to aggregate rewards?
TL;DR: Yes. As of today, a joiner in a pool can expect to earn double the amount than a solo staker.
Please continue reading if you’d like to see the explanation:
Ken Smith details in this talk at Devcon his research about it. Feel free to watch the video to get more info, or read his report - find it in References below. In short, the answer is yes, it makes sense.
Because there is a long term distribution of very few blocks with very high rewards, we have a very low median payout per block in rewards, but a higher average. This means that a single validator is likely to stay around the median, but a pool is likely to capture something closer to the average for its members.
For the data that I offered in the TL;DR, in this dashboard we can see that a solo staker would be expected to earn around the median, and a participant in the pool around the average. That’s currently more than double the amount.
Initial Design for the Solo Stakers Smoothing Pool
A MEV Smoothing Pool that allows users to set their fee recipient to it and receive overall higher fees. Since this service effectively generates extra revenue for the validators, a fee can be introduced to align interests and have a win-win scenario. It’s also a way for Dappnode to achieve sources of revenue that are not extractive from the user, like donations, and rely on the collaboration of the team and the users to generate surplus value.
User Flow:
1) Subscription
1a) Active subscription:
Users can subscribe to the pool via UI by signing a message with the deposit address of the Validator an setting a poolRecipient
. The registration will be completed as soon as there’s a successful block proposed from the validator that effectively sends the MEV rewards to the pool.
1b) Default subscription
Users will also be registered automatically when they send a MEV block reward to the pool. Their deposit address will be set as the poolRecipient
.
2) Accruing Rewards
Rewards are accrued automatically from the moment of the first deposit into the pool.
Users can check the UI to see their pendingBalance
.
3) Claiming Rewards
Each period, those validators who have proposed a block and sent the rewards to the MEV Smoothing pool will see their pendingBalance
turned into availableBalance
. Users can claim their availableBalance
at any time.
4) Unsubscribing from the pool
Users can unsubscribe from the pool at any time by calling unsubscribe
. Their availableBalance
will still be available, but their pendingBalance
will be split among the rest of the pool. Hence it is recommended that they exit during the same period when they successfully send MEV rewards to the pool and they get their pendingBalance
turned to availableBalance
.
4) Dealing with cheaters
Those who are subscribed to the Pool and are caught sending MEV rewards to a different address other than the Smoothing Pool, will be banned. Their pendingRewards
will be split among the rest of the participants of the pool and they won’t be able to join the pool again.
Other considerations
There should be 4 smoothing pools:
- OFAC Compliant
- Non-compliant
- Ethical
- Max-profit
to respect people’s desire to comply with OFAC sanctions or not. The OFAC compliant might have a higher fee to dedicate to anti-censorship activities.
Architecture
Needs 3 pieces:
- Smart Contract - to register, unregister, receive the rewards and distribute them.
- Oracle - to update the balances of the accounts, detect default registrations, cheaters and bans.
- UI - to facilitate subscription and unsubscription, consult balances and to claim.
Smart contract design:
Methods
Subscribe
SC Subscription
To subscribe you will need to provide a Proof that you control the deposit address of a validator. Upon provision of the proof, you will be able to set the poolRecipient
- the address where you will be able to claim the rewards.
Merkle Tree subscriptions:
- Index Validator
- Leaf: Deposit address
- User calls SC to suscribe:
-
ValidatorID
,MTproof[]
,poolRecipient
- Check agains the merkle tree
msg.sender
is deposit address
-
Mapping SC: ValidatorToSuscription (Validator → Suscription);
Suscriptions: address depositAddress, uint64 timestampStart, uint64 timestampEnd, address poolRecipient
offChain Suscription
- Oracle Detects a fee is recieved in the smoothing pool contract
- Suscribe the deposit address of that validator and set it as
poolRecipient
- Oracles suscriptions:
- Oracle can suscribe another address (Array)
- (ValidatorID, timestampStart, depositAddress)[]
- Oracle can suscribe another address (Array)
- Suscribe the deposit address of that validator and set it as
The centralized service (“Offchain” above) registers deposit address per validator in the SC.
NEED: AN AUDITABLE SERVICE TO CHECK SIGNATURES AND REGISTER VALID ONES IN THE SMART CONTRACT
Unsuscribe
- CAll to the unsuscribe method, only depositAddress
- ValidatorID
- Update thetimestampEnd
. - The user will be able to claim the available balance of that validator at when the oracle does the next update.
changePoolRecipient
- Call, only depositAddress
- ValidatorID, newPoolRecipeint
claimRewards
Users will submit a proof that they can claim availableBalance
.
- Merkle tree containg all the corresponding balances to each withdrawal address (or deposit address)
- Leaf:
- Address (deposit)
- ValidatorIDs[] → can be deleted
- Available balance
- Pending balance (Will be unlocked once a block is proposed and the fee recipeint is correct)
- Unbann balance
- Pool recipient → Authorized account to claim funds (default deposit addr)
- Leaf:
0xAAA (deposit addr)
0xBBB ( Pool recipient)
Update Claimed(0xAAA)
Mapping SC: Claimed (address → ClaimedBalance);
Mapping SC: ValidatorToSuscription (Validator → Suscription);
Suscriptions: uint32 ValidatorID, uint64 timestampStart, uint64 timestampEnd, bool banned, feeRecipient
unbanUser (banned user can call it to be “unbanned”)
- CAll to the unBanUser method
- User should pay the Unban balance of the leaf of the MT
banUser (Oracle can call it when detects foul play)
- A block comes and you don’t send the reward to the pool
- Oracle detects that and splits your pending balance among the rest and rest of participants, putting your Pending balance to 0
- Puts your pending balance in negative, so it’s recorded in the MT leaf - this is done so we can generate a proof that this is the amount and call the unban.
Oracle
Validator poposes a block from validator list:
- Check if is the correct fee recipient
- If not, ban validators, and redistribute pending balance to the rest of validators.
- Distribute fee between suscribed validators
- Consolidate state
Pending Blanace → Available Balance
Tables
- Subscriptions → ValidatorID, DepositAddress
Debates
- Deposit Addres vs. Withdrawal Address
Who can set the the poolRecipient
address?
UI
- What needs to show?
Future
- Subscribe: signing with withdrawal address
Merkle tree optimistic - Store in SC in every slot of time how many validatores suscribed
- Prove:
- Easy to prove is if someone cheated with zero knowledge, bc fee recipeint is different
- Checking the difference balance of the SC can be calcualted the balance of every validator suscribed
Current Questions
-
What are the consequences of marking the deposit address controller of the validator and
poolRecipient
?- What are the cases when giving the control of the
poolRecipient
address to the deposit address would actually disserve the real owner of the ETH of the validator?
- What are the cases when giving the control of the
-
Are there extra considerations for making the pool mainly targeted to Solo Stakers than a generic pool?
-
Would overcompliooors consider rewards tainted if they received profits from a pool that accepts any relayer? Even if they only propose blocks from compliant relayers.
-
What happens if someone sends ETH to the pool? Unlikely, but how can we cover it? Split it regularly among the users? What happens if it’s Tornado ETH?
-
When banning, should we ban all related validators? Those would be the validators that are related to the same deposit address.
Next steps:
In the next few days we will publish for public scrutiny:
-
Smart contract design* Done 25/10/22 - Oracle design
- UI design
Would be also happy to do a community call to explain to the community and hear more feedback about it! Planning one for this week if possible.
Resources:
Rocket Pool Smoothing Pool
- Rocket Pool’s Design Rationale
- Contracts
- MEV Smoothing Research GDoc, Repo
- RP’s smoothing pool Dune Dashboard