-
Notifications
You must be signed in to change notification settings - Fork 4
fnanni - Execution Layer rewards are lost #174
Comments
request poc I need more information/resources for this issue so need to facilitate discussion. |
PoC requested from @fnanni-0 Requests remaining: 6 |
@nevillehuang I forgot to link to the Rio docs: https://docs.rio.network/rio-architecture/deposits-and-withdraws/reward-distributor. Can we get @solimander input here? Reading this issue again, there is a chance I misunderstood the docs. Is the Reward Distributor contract expected to be able to receive Execution Layer rewards, i.e. be set as blocks fee_recipient address? If the answer is yes:From the Solidity docs: "A contract without a receive Ether function can receive Ether as a recipient of a coinbase transaction". The recipient of a coinbase transaction post-merge is the address defined by the block proposer in the
As an example go to etherscan and select any block recently produced. Check the fee recipient address. Check how its ETH balance is updated ("credited") at every transaction included in the block even though there is no explicit transaction to the fee recipient address (for example, balance update of beaverbuild here). |
Our operators will run MEV-Boost, which sets the fee recipient to the builder, who then transfers rewards to the proposer, which triggers the receive function. However, it seems worth adding a function to manually push rewards just in case. How does that affect severity here? |
@solimander I have a few questions:
|
I'm unsure, but that'd make sense. I'll be adding a function to manually split and push rewards regardless. |
This issue seems out of scope and hinges on external admin integrations. But leaving open for escalation period |
The protocol team fixed this issue in the following PRs/commits: |
Escalate The info that the RioLRTRewardDistributor is meant to receive the execution layer rewards is not mentioned anywhere. The mentioned docs state |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
I disagree. The Reward Distributor is expected to receive and distribute rewards. “the ability to receive ETH via the Ethereum Execution Layer or EigenPod rewards”, in this context, seems to mean Execution Layer rewards, which the sponsor confirmed. EL rewards are credited, not transferred, and therefore cannot be currently distributed. Following up on the prior discussion with the sponsor, regarding operators' obligation to use mev-boost: builders replace the proposer's fee recipient address with their own and directly transfer funds to the former, triggering the receive function. mev-boost is not mentioned in Rio’s docs, but still EL rewards will sometimes be lost:
For operators aiming for optimal performance, settings 1, 2, and 3 are crucial. RioLRTRewardDistributor assumes the fee recipient role in these instances, causing priority fees and MEV funds to get stuck. |
We only mention MEV-Boost in our operator docs. Valid in that execution layer rewards would be stuck in the fallback case. |
I believe @10xhash is correct, this seems to be out of scope and invalid based on the following sherlock rule unless otherwise stated in documentation, which is not present.
|
@nevillehuang could you elaborate on why do you consider EL rewards sent to RioLRTRewardDistributor The documentation (here and here) mentions that EL rewards are expected and RioLRTRewardDistributor must handle them. In addition, it is stated in the operators docs that whitelisted operators must make sure this happens (otherwise I guess the RioDAO would delist operators who disobey?). Third, go to the FAQs section in https://goerli.rio.network/ and you will see:
Furthermore, rewards expected to be received by RioLRTRewardDistributor (EL rewards included) are distributed to the treasury, the operatorRewardPool and the depositPool. This means that EL rewards become:
There are many places in which it is explicitly or implicitly pointed at the fact that Execution Layer rewards are part of Rio's protocol rewards and the sponsor confirmed this. |
@fnanni-0 You are correct, thanks for pointing me to the right resource. I believe this issue is valid and should remain as it is. |
I believe that Execution Layer rewards are a part of the initial design, but I don't see why would the
Please note that a word "depositing" is used, which implies that the deposit logic is triggered during these operations, and the balance isn't just incremented. Aside from that, the MEV Bosst is mentioned in the docs:
In order to keep this issue valid, there needs to be an expectation of |
@Czar102 I think this is where it's the clearest. The Reward Distributor contract is mentioned and the instruction to set it as the fee recipient means that it is expected to receive execution layer rewards directly.
Note that even with mev-boost as a requirement (which the docs don't seem to say it's a must), setting fee recipient to the Reward Distributor contract means that in fallback cases it will receive EL rewards directly, as explain in my previous comment. In case it matters, the documentation provided in the contest readme (https://docs.rio.network/) references the operator docs, quoted above, in the section Regarding,
I guess the operator docs are enough, but let me elaborate a bit more. EigenLayer doesn't handle execution layer rewards, so it's evident that they must be handled differently. There are no other contracts in Rio protocol for this purpose except for RioLRTRewardDistributor and nowhere it is explained that there could be a special method for handling EL rewards before sending them to RioLRTRewardDistributor. The most straight forward, intuitive way is to simply send the rewards directly. Here are all the other chunks of documentation and comments linked in this discussion that seem to me to clearly state that EL rewards are or could be received directly by the
Regarding the last quote, you wrote:
You are right in the sense that the deposit logic is referenced, but I think the link might be incorrect. "deposited when the daily epoch ends" is contradictory, since the deposit flow and the rebalance flow are two separate things. But "depositing" is use in the context of the Deposit Pool contract receiving rewards which is well documented, because the Reward Distributor contract sends ETH to it which can be withdrawn/staked during rebalancing. |
Great points, @fnanni-0. @nevillehuang I think the message you quoted actually supports @fnanni-0's point, am I understanding correctly?
@fnanni-0 does Rio have control over when the Execution Layer Rewards are sent if they are sent directly? I think lack of my knowledge about it didn't allow me to fully understand the meaning of the last quote from the docs about daily deposits of rewards. |
@Czar102 I don't think so. They are sent to the Reward Distributor directly when a validator controlled by an operator registered in Rio is selected as block proposer and one of these three scenarios happens (or if mev-boost is not used). Does this answer your question?
In case it wasn't clear, the Deposit Pool should receive the rewards from the Reward Distributor at any time, independently of the rebalance execution, like all deposits. It's the rebalancing of these deposits (rewards included) that happens daily. Anyway, this doesn't seem very relevant here. |
I see, thank you for this elaboration. It seems that this is indeed a valid concern. @solimander @nevillehuang @10xhash @mstpr if you still diagree, please elaborate what are we misunderstanding. Planning to reject the escalation and leave the issue as is. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
Fixed |
The Lead Senior Watson signed off on the fix. |
fnanni
high
Execution Layer rewards are lost
Summary
According to Rio Network Docs: "The Reward Distributor contract (RioLRTRewardDistributor) has the ability to receive ETH via the Ethereum Execution Layer or EigenPod rewards and then distribute those rewards". However, this is only true for EigenPod rewards. Execution Layer rewards are not accounted for and lost.
Vulnerability Detail
Execution Layer rewards are not distributed through plain ETH transfers. Instead the balance of the block proposer fee recipient's address is directly updated. If the fee recipient getting the EL rewards is a smart contract, this means that the fallback/receive function is not called. Actually, a smart contract could receive EL rewards even if these functions are not defined.
The RioLRTRewardDistributor contract relies solely on its receive function to distribute rewards. EL rewards which don't trigger this function are not accounted in the smart contract and there is no way of distributing them.
Impact
Execution Layer rewards are lost.
Code Snippet
Tool used
Manual Review
Recommendation
Add a method to manually distribute EL rewards. For example:
The text was updated successfully, but these errors were encountered: