Indexers are vital to running the network; they pay for server expenses and additional costs for sending Ethereum transactions. The network is currently distributing indexing rewards every epoch, stake them by default, and then subject to a 28 thawing period before release. Additionally, any potential rewards are locked into TokenLock contracts requiring, in some cases, unstaking much capital to withdraw them.
This proposal allows indexers to withdraw indexing rewards without going through the thawing period and eventually sending them to an arbitrary beneficiary address.
Implementation
Staking Contract
By default, every time closeAllocation() is called by an indexer with a correct POI presented, the getRewards() function of the RewardsManager is used to calculate the amount of tokens to distribute for that allocation. Those rewards are minted and then always staked to the indexer address.
Changes
Introduce a function to allow any indexer to set the rewards destination.
function setRewardsDestination(RewardsDestination _destination) external;
It can be set to any of these options:
RewardsDestination.stake
RewardsDestination.rewardPool
If set to “stake” any rewards will be staked; if set to “rewardsPool” the tokens will be deposited into an indexer-specific rewards pool for later withdrawal.
Update function _distributeRewards(address _allocationID, address _indexer) private to check the rewards destination and stake or deposit into the rewards pool.
// -- Current implementation --
// Add the rest of the rewards to the indexer stake
if (indexerRewards > 0) {
// TODO: << check if rewards destination is set to stake or deposit into rewards pool >>
_stake(_indexer, indexerRewards);
}
Add a function to withdraw from the rewards pool function withdrawRewards(address _beneficiary) external
This function is called by the indexer passing the beneficiary address where the contract should send the accumulated rewards.
Highlights
By using a different rewards pool it is possible to avoid staking and set the funds apart for an indexer to withdraw them to an address different than a TokenLock contract that would otherwise lock the funds.
The rewards pool allows to collect rewards from multiple allocations and the indexer decides when it is gas efficient to withdraw them.
By setting the rewards destination once using a setRewardsDestination function we do not need to change the close allocation function signature.
The feature will work for rewards collected after its implementation, past rewards remain staked.
We can implement the same mechanism for the claimed rewards from the rebate pool.
Just for clarity, would this method still require a 28 day thawing period? You mention “withdrawal”, but just checking if you mean it in the literal sense, as far as our current terminolgy goes. @ari
The idea is that all rewards sent to the rewards pool can be taken out from the contract using withdrawRewards() with no thawing period, while anything re-staked goes through the default unstake() then withdraw() with thawing period.
The proposal is concise and addresses the concern many indexers are facing.
The option to trigger withdrawal at indexers’ convenience is great in managing the eth expenditure as well as accounting for tax purposes and many indexers are also concerned.
Thanks @ari ! Looking forward to have the proposal deployed on the testnet.
Hi, this is a good proposal. But I would like to clarify one moment. Has it been discussed that such a system could be used to withdraw delegators rewards? In case the delegator has an agreement with the indexer, it would be set indexing cut to 100% and then distribute part of the rewards to the delegator from rewardsDestination address. Is this behavior acceptable or should there be a limit on the amount of withdrawal?
Thank you for this proposal. I’m generally in favour, though i’d like to ask about some options (not) taken.
Why instead of RewardsDestination.rewardPool explicitly set the intended destination address ? Then the indexer receives their rewards without needing to spend extra gas to withdrawRewards ?
Some people suggested being able to set a split between restake and withdraw, could this be easily added to the given proposal ?
If the cut is always 100% I don’t see why it’s anyone else’s business what happens with the rewards - Indexers are free to make all the deals they want. The problems come when either A) Cuts are changed a lot (not suggesting you would do that, just an example), attracting random delegation and/or B)Misguided delegators ape into a 100% indexer - both have the potential to look very bad from an optics point of view. I can’t think of a solution to either of those problems.
Okay, trying to clarify what you meant :
Is it that you want this to be made possible, in addition to the proposal ?
Or is it that you are afraid the proposal would make such behaviour possible ?
In general, I am fine with what described in the proposal. I just wanted to bring it up for discussion. As it could become one of the indexer services - distribution of inflation rewards to delegators without the 28-day locks. All indexer needs to do is to write and deploy a distribution smartcontract to the network and to specify its address as the rewardDestination address.
I just want to understand how the team and community feel about this.
Ah ok, got it. I hadn’t even thought of that in reading your initial post. That does seem problematic. The only immediate solution I can see to such behaviour is for delegators to be able to access their accrued rewards instantly too, while their original stake remains frozen.
I’d like to propose a modification to this proposal:
Allow indexer to set a _beneficiary, using setRewardsDestination E.g.: function setRewardsDestination(address _beneficiary) external;.
If _beneficiary is 0x0, future rewards are restaked.
When _beneficiary is set, rewards are put into the Reward Pool, and set the destination of all future withdrawRewards() calls to beneficiary.
withdrawRewards(address _indexer) could then be called by anyone, but the tokens would always be transferred to the intended _beneficiary
The rationale is to remove the need to access the indexer account for regular operations, similarly to what we have with the operator account. The indexer address could potentially hold a significant value, so allowing day-to-day operations like withdrawRewards() to be called by another account requiring only basic security measures would remove significant risks to the indexers.
Thanks for moving so quickly on this @ari. I support your proposal in its current state and am looking forward to helping test this on testnet and for the upgrade to be implemented on mainnet.
We agree in general with the proposal made and looking forward to test the procedure on the new testnet.
One extra suggestion from our side - if it would be possible to optimize the gas fees in the whole network. This would come with some trade-offs - for example if a delegator claims the rewards then the rewards will be distributed for all delegators staking with an indexer, including the indexer itself, paying one transaction fee. But maybe there should be a separated proposal/thread for this.
The point of freezing funds for 28 days is, IMHO limits the ability for participants to respond immediately to market conditions and then open the gates to arbitrage and exploits.
Rather than changing the protocol lockup period, why wouldn’t this be a place where third parties could provide loans to cover operational expenses as traditional businesses do? This feels akin to calling customers and demanding them to pay their invoices early, no?
Why would by setting a destination address still want to payout into a separate reward pool, which would require extra gas to withdraw from there ? Instead of immediately paying that to the specified address, which would be included in the gas for closing the allocation and immediately address your security concern is a safe way as that gets called by the operator key ?
People’s capital (stake / delegation) remains subject to 28 thawing. It’s only rewards that get exempted.
Indexers who are putting in massive time + capital don’t need to get slapped with interests on a loan they don’t need. Indexers simply need to be able to access their rewards, without being required breaking up shop (because of a smart contract limitation that as i understand wasn’t intended to begin with).