omgnetwork / plasma-contracts

Root chain contracts for Plasma
Apache License 2.0
114 stars 66 forks source link

[Process Exit Bounty] Design decisions #658

Open souradeep-das opened 4 years ago

souradeep-das commented 4 years ago

Issue Type

[ ] bug report
[x] feature request

Overview

Based on https://github.com/omgnetwork/plasma-contracts/issues/607 This not only removes an extra step while reclaiming exiting funds but also enforces the idea of everyone paying their part for processing their exits rather than passing on the responsibility.

Flow with process exit bounty

  1. User starts exit with providing exit bond + process exit bounty 1.a. Providing the bounty is a compulsion( providing bounty should be more economical ) but the user could process their own exits to get the bounty back
  2. Ignoring path (1.a), Someone periodically checks for the exit queue size
  3. When there is/are new finalized exits in the queue, he processes the exit
  4. He receives exit bounty for each exits he has processed

Design Decisions

Alternate approach

Since the exit bond is only returned for successful exits, we could combine the bond and bounty and take in value of whichever is higher and refer it to be the bond.

When exits are challenged → the bond is given to the challenger

When exits are finalized → if bounty >= bond, return nothing if bond > bounty, return bond - bounty

But this could increase the complexity, so having separate exit and bounty is the preferred way.

Out of Scope

Having a fixed actor for processing exits is out of scope for now. Allowing anyone to process exits and claim bounty should be good for a start

kevsul commented 4 years ago

I see where you're going with the alternative approach - use the bond to reimburse whoever calls processExits. It's not a bad idea... 🤔 Currently though, the size of the bond is not related to gas price. We considered it, but decided that it was too hard to do safely, because if manipulating the gas price can affect the exit bond size then it affects the security model.

I don't think that's a problem with the bounty though. A miner could include a startExit tx with a 0 gas price, thus making process_exit_bounty 0. This just means that there's no bounty for processing the exit, which is what we have now.

What happens to bounty when exit is challenged?

I would lean towards awarding it to the challenger. I don't see any benefit in burning it.

What value of Bounty ensures there is enough incentives always?

It's impossible to predict gas prices :) But I think we really only have to come close to covering the cost of processing an exit, so that a user is not penalised too much for processing an exit that's ahead of their own exit.

What should the value of K be? Should the value of K be updatable?

I favour keeping K low. Effectively we're making a user pay for their exit upfront. We don't want to make it too expensive to start an exit. My feeling is that it doesn't need to be updatable, let's just pick a value (e.g. 20) and run some simulations with that.

kevsul commented 4 years ago

What path should be suitable for in-flight exits?

The simplest is probably for whoever starts the in-flight exit to put up the bounty. I'm not sure if it's very fair though - they already have to pay gas + bond for starting an exit, and then have to piggyback as well in order to actually exit any funds.

Alternatively we could require a bounty on each piggyback, which all get added together and paid out when processed. This is more complicated to calculate the bounty size though...

souradeep-das commented 4 years ago

A miner could include a startExit tx with a 0 gas price

Yes, makes sense. Thanks for pointing out 👍

Awesome, Trying to run simulations with 110 or 120% margin

Yes, I think for the IFEs the bounty on each piggyback would definitely make more sense, though it means a whole new way of gathering bounty. But do we really expect a lot of IFE's ? If not, we could go with the first approach? (its really unfair) 😄

boolafish commented 4 years ago

As for splitting on piggyback, also need to be aware that probably not all inputs/outputs would be piggybacked.

I would lean towards awarding it to the challenger. I don't see any benefit in burning it.

If we are doing so, we might want to fully delete the exit from priority queue whenever challenged. Currently a challenged exit is still in the queue and would still cause a bit of gas on exit. The gas can be lower or higher as challenge would have removed the exit data from storage while for non-challenged exit, the process exit would delete the storage and get some gas rewards back.


Some tweaks for possible improvement:

  1. there is the function gasLeft in solidity. We can probably leverage that to calculate the real gas used.
  2. I would like to propose we lock whatever exit bounty we have in some contract. We always try to return the actual gas back to user who calls process exit to cover the call from the contract holding exit bounty. We will try to drag the fund from exit bounty. However, we as the operator would monitor the water level of the fund there. If it is too low (if our exit bounty formula does not fit our real cost) we might consider to throw some funds there.
souradeep-das commented 4 years ago

So for splitting on piggybacks the bounty, we could give away the bounty for each piggyback instead. So the bounty might be different for each exit. And also considering the first approach of in-flight exit initiator to pay for the bounty, how much should we really take the size of bounty to be (assuming not everyone piggybacks and the gas used for processing is low) Also gas used for canonical and non-canonical might be different.

Whatever Alice pays -> Bob in comparision to Alice pays bounty -> Vault -> Bob pulls apt funds from Vault according to gas I guess the paying out in terms of the real gas used could be good, but could lead to irregularities when someone processes too many exits at once. Instead we could give away the bounty for each exit? (eg: You process 5 exits, you get bounty associated with those 5 exits?)

As for the operator monitoring the level of funds, could we just allow it to be the decision of the person who is processing if he wants to process? I did some calculations with the gas prices of the last 559 days. And a constant ratio of 120% (K = 120) is good enough to provide profits for the processor like 81% of times. And if it's a single actor who is processing exits we could even reduce K to even 110 or lower. https://docs.google.com/spreadsheets/d/1OVHLHEZcSe_LtLQQNioKD1OfRF-KYwI1vJUyoMPbOWI/edit?usp=sharing

kevsul commented 4 years ago

It seems like there are 2 options:

  1. To incentivise calling processExits by rewarding the caller with a (small) amount of ETH. The person who wishes to exit pays this extra ETH as the bounty when calling startExit. It's unlikely that the person who starts the exit will also process it, so this means that an exit is slightly more expensive for the exiter. Note that due to gas volatility we can't guarantee that the bounty will cover the cost of processing the exit.

  2. To make calling processExits free by awarding the caller exactly the amount of gas spent. This avoids users being penalised when they want to exit immediately and there are already exits before theirs in the queue. The ETH to reimburse the gas cost comes from a pool of ETH that is added to when calling startExit. This pool can be topped up by the operator at any time. Because of gas price volatility, this may make the exit slightly more expensive for the exiter (but less so than with option 1).

Thoughts or preferences?

boolafish commented 4 years ago

If we are auto processing the exits, option 2 feels more like a good operator 😅 so we are not trying to collect one more fee again for people exiting the network.

However, if we do not want to make it one of our responsibility to process exits, the 1 is good. Probably better than 2.

thec00n commented 4 years ago

I also favor 1. I think we can implement a similar update mechanism than for the other bonds?

souradeep-das commented 4 years ago

Considering option 1 :- Let's assume the bounty is not enough to cover the cost of processing the exit due to gas volatility, and so no one processes the exit and it remains in the queue. But when a second exit is added to the queue, the gas usage for processing both these exits together is going to be lower than the total gas usage for processing individually. You could easily make up the difference of the bounty and processing cost by say, processing two exits at a time. So a very very low chance of losing funds on processing.
Furthermore, this could also do away with the need to add any extra amount of eth to the bounty ( removing the constant multiplier) Will add some calculations to check this. Update: though we can never really fully guarantee that the cumulative bounties will add up to cover the processing exit at any point, we could possibly remove the need to send in any extra amount of eth to the bounty

thec00n commented 4 years ago

I propose to keep this really simple and just have a way to update the amount through the maintainer. I don't think we need to guarantee that this is profitable at all times. Gas prices swing wildly and during the peeks it might not be economical to process exits and that's ok.

souradeep-das commented 4 years ago

For Challenged exits: I think the exit data is deleted on process exits for both challenged and non-challenged exit. In that case though it still costs some gas for the challenge exit in queue, you still get some gas reward for deleting storage.

kevsul commented 4 years ago

Another thing - as we've seen in the past, any transaction that pays out to the sender will get front run. We may want to add some basic front running protection, like we did with challenging exits

souradeep-das commented 4 years ago

👍 great point!

souradeep-das commented 4 years ago

Considering the Process Exit Bounty for In-flight exits:- The gas usage for processing an IFE with one piggybacked input/output is approximately 979,000 and for every successive piggybacked output/input we need around 69,000 gas more According to the path of providing the process exit bounty for every piggyback :-

One way could be having around 500,000 bounty for every piggyback, assuming both the inputs and outputs are piggybacked. but that would definitely make it costlier to piggyback. Otherwise a mix of both of taking bounty while starting (around 840,880) and successively 34530 (69,000 / 2) for every piggyback Any ideas or suggestions? @boolafish @pgebal

boolafish commented 4 years ago

From the point of simplicity, probably just add the bond on piggyback but I don't think we should assume both inputs and outputs are piggybacked. Honestly probably assuming 1~2 are piggybacked might be a more realistic number.

taking bounty while starting (around 840,880) and successively 34530 (69,000 / 2) for every piggyback

curious how is the portion of starting IFE and piggyback is decided here?

souradeep-das commented 4 years ago

So going with the accepting bounty for each piggyback, if we consider processing an IFE with two piggybacks, the gas should be around 1022918, We could move then with a bounty equal to 500,000 gasPrice for each piggyback. The downside however, when there is only one piggyback the bounty will not be enough to process ( since processing an IFE with one piggyback would be more close to 979,000 gasPrice ), but in that case the person who piggybacked can process exit himself if no one else chooses to.

curious how is the portion of starting IFE and piggyback is decided here?

So I tried to approximate this from these facts - Gas for exiting one piggybacked input/output = 979,000 Increase of gas per piggyback(Gp) = 69,000 Assume taking 840,880 with startIFE, and then 34530 for every piggyback We have 840,880 + 34530 + 34530 = 909940 for two piggybacks Here the 34530 ( half of Gp) assumes though that the user will piggyback both the inputs and outputs

The bounty per piggyback way should be ideal and simpler, only could increase the cost of piggyback a little bit

kevsul commented 4 years ago

Take aways from call about the exit bounties:

boolafish commented 4 years ago

https://omgnetworkhq.slack.com/archives/C7V603752/p1599537940007200

TL;DR we might want to reconsider the "Alternate approach" where we use single value for bond and bounty after we discard the dynamic gas price for bounty. As the 2 flows are so similar now.

kevsul commented 4 years ago

Simplifying the code is always good, but I'm kind of worried that mixing the bond and bounty concepts will be confusing. And the bond should still disincentivise invalid exits.

Or maybe it's just that you get back less bond than you put up, as a cost of having your exit processed. For example:

  1. Alice starts valid exit, she pays X bond

  2. If Alice pays the gas to process the exit, she gets the entire X bond back

  3. If Bob pays the gas to process the exit, Bob gets Y back to cover the gas, Alice gets (X - Y) back

  4. Alice starts an invalid exit, she pays X bond

  5. Bob challenges and gets the entire X bond

The value of the bond should be sufficiently larger than Y so that Alice is incentivised to start a valid exit.

souradeep-das commented 4 years ago

sounds fair enough. Since, cost of processing > cost of challenge invalid exit @kevsul about the concern for the value of bond, shouldn't it be okay for Bond = Y as well? ((bond >=Y) Or am i missing something?

kevsul commented 4 years ago

The bond should cover the cost of either challenging or processing the exit. So let's find out which of those has a higher cost and set the bond to that.