# Optimistic Oracle + Fraud Proofs to Mitigate Consensus Layer Deposit Frontrunning

**URL:** <https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452>\
**Category:** Proposals\
**Created:** [June 19, 2022, 7:22pm UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452 "2022-06-19T19:22:11Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![bbuddha](https://avatars.discourse-cdn.com/v4/letter/b/13edae/32.png) [@bbuddha](https://research.lido.fi/u/bbuddha)\
**Post date:** [June 19, 2022, 7:22pm UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/1 "2022-06-19T19:22:11Z")

</div>

Please read this [informative post](https://research.lido.fi/t/mitigations-for-deposit-front-running-vulnerability/1239) from @skozin (especially part d!) before reading the rest of this document.

We propose a new system for mitigating the frontrunning deposit issues that does not require stETH holders to trust the Lido Oracle.

## The problem

Here’s a quick summary of the problem itself.

When stETH minters deposit their ETH into Lido, they are immidiately minted a corresponding amount of stETH. When the deposited ETH is eventually deposited into the consensus layer deposit contract, in order to ensure the withdrawal credentials of the consensus layer deposit are, in fact, pointed to the Lido contracts, stETH holders rely on a trusted Lido Oracle to verify that a previous deposit with the pending deposit’s public key doesn’t exist (see this [here](https://github.com/lidofinance/lido-dao/blob/816bf1d0995ba5cfdfc264de4acda34a7fe93eba/contracts/0.8.9/DepositSecurityModule.sol#L408)). This is done through reaching a signature quorum of the Lido Oracle guardians certifying the current merkle root in the consensus layer deposit contract.

Once the Oracle has certified exclusion from the merkle root, the deposit is initiated and the ETH previously deposited into Lido is staked. The issue here arises if the Lido Oracle maliciously certifies a deposit to a validator who has already deposited. Then, some non-Lido entity has control over the 32 ETH deposit’s withdrawal credentials, meaning that stETH is no longer backed 1:1 by ETH on the beacon chain.

It is important to note a couple facts before proceeding:

1. This system requires stETH holders to trust the Lido Oracle to keep the backing of stETH and not steal all pending ETH deposits into Lido.
2. The oracle is currently and 4 out of 6 multisig approved by the Lido DAO (as of June 18th, 2022).
3. There is an ability to [pause deposits](https://github.com/lidofinance/lido-dao/blob/816bf1d0995ba5cfdfc264de4acda34a7fe93eba/contracts/0.8.9/DepositSecurityModule.sol#L337) if a guardian provides a signature to do so, however this still requires stETH holders to trust 1 of the 6 guardians to pause deposits when needed.

Although the Lido DAO approval is a good security measure, it isn’t equivalent to stETH holders having to trust the DAO itself.

## The trustless solution

### Description

The new system we propose is an extension of the current system that does not require stETH holders to trust that the Lido Oracle will not steal all pending deposits and “unback” stETH. In addition, the stETH holders just need to assume that 1 cryptoeconomically incentivised watcher (which they can run!) is watching the system rather than assuming that 1 of the 6 guardians is watching.

At the core of the new, proposed system is a idea of a _rainy day fund_ (RDF). In the new system, the Lido contracts do not allow more than the balance of the RDF to be deposited into the consensus layer deposit contract per day. Ether is still sent to the deposit contract optimistically after a quorum of guardians is reached, but, now, anyone can submit a fraud proof on chain proving that there was a previous deposit corresponding to a certain public key that the Lido Oracle certified within a day of the malicious deposit. Note that this fraud proof is simply a valid merkle proof of the previous deposit against the deposit root certified by the Lido Oracle.

If a valid fraud proof is submitted, the Lido deposit flow is stalled and requires DAO intervention. The DAO must ban the signing guardians and malicious stakers as neccesary. The submitter of the fraud proof should also be rewarded a small amount more than the fee paid for the fraud proof transaction to cryptoeconomically incentivise them to do so. In addition, the fraud proof contracts should withdraw 32 ETH from the RDF for every fraudulent deposit and either:

1. Allow stETH holders to redeem the ETH at the correct, yield adjusted ratio
2. Wait until the system is up and running again and deposit the ETH into the deposit contract

Another option is to completely get rid of the RDF and purely dilute LDO enough to swap for ETH and then proceed with one of the options. This system would require LDO holders to take on risk by trusting the oracle and thus to possibly be compensated for doing so.

### Fraud proof windows and RDF backing

To be precise, the reason a 1 day fraud proof window is required is to be resistant to Ethereum censorship attacks. If fraud proofs are censored, malicious deposits will not be accounted for in the Lido contracts, leading to the “unbacking” of stETH. This is precisely the reason that the RDF needs to hold 1 day’s worth of deposits. Since fraud proofs can arrive 1 day late, the Lido Oracle could have been certifiying invalid deposits for a day. Thus, the RDF needs to be able to provide enough funds to compensate for the sum of the value of all malicious deposits the Lido Oracle could have certified during the day, which is just the maximum amount allowed to be deposited from Lido per day.

We, personally, believe the fraud proof window can theoretically be reduced down to 1 hour or 30 minutes as followed by [Nomad](https://docs.nomad.xyz/). This would only require the RDF to hold the maximum amount allowed to be deposited by Lido in 1 hour or 30 minutes, which increases capital efficiency. Of course, this reduction is at the cost of tolerance to the base layers censorship resistance properties.

## Final thoughts

The new system has some implementation complexity as the fraud proof system needs to be built. Although the fraud proofs themselves are not very complex, the integration with the rest of the system may be more so. On the other hand, we believe such a system would be important for reducing trust assumptions for stETH holders.

-bbuddha, toowoundup

---

<div class="post-metadata">

**Author:** ![ujenjt](https://dub1.discourse-cdn.com/flex013/user_avatar/research.lido.fi/ujenjt/32/240_2.png) [@ujenjt](https://research.lido.fi/u/ujenjt)\
**Post date:** [June 20, 2022, 9:55am UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/2 "2022-06-20T09:55:45Z")

</div>

First of all, thank you for such a detailed proposal, this is one of the angles from which we have not yet considered the problem. However, I did not fully understand how exactly a smart contract can check fraud proof? And how fraud proof will look like? Is it about checking that deposit contract merkle root contains two deposits with the same pubkey and different withdrawal credentials?

---

<div class="post-metadata">

**Author:** ![bbuddha](https://avatars.discourse-cdn.com/v4/letter/b/13edae/32.png) [@bbuddha](https://research.lido.fi/u/bbuddha)\
**Post date:** [June 20, 2022, 6:41pm UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/3 "2022-06-20T18:41:12Z")

</div>

Thanks for the kind words 🙂

But, yeah, that’s exactly what we were thinking! Whenever Lido deposits are batched to the consensus layer deposit contract, the Oracle certified (current) merkle root would be stored in the fraud proof contracts along with all the public keys of the validators that were deposited for (or perhaps the hash of all of them). Then, anyone would have a day to prove any number of previous deposits against the stored merkle root that have the same public key as one of the public keys of the validators that was deposited for.

For example, say the Lido Oracle certified merkle root `deposit_merkle_root` and, thus, deposits of 32 ETH were made for validators with public keys `v_1`, `v_2`, and `v_3`. Suppose the Lido oracle was corrupted and the staking operators for `v_1` and `v_3` were corrupt and pre-deposited into the consensus layer deposit contract with public keys `v_1` and `v_3`, therefore taking control of any deposits made to `v_1` and `v_3`. Now, any watcher can transparently see that 32 ETH has been stolen from the protocol and provide a merkle proof of a deposit `d_1` against `deposit_merkle_root` that has public key `v_1` to the new fraud proof contract, which verifies the proof and and subsequently pauses the deposit flow and perhaps slashes or kicks out the guardians who signed `deposit_merkle_root`. In addition 32 ETH will be withdrawn from the RDF to compensate the protocol for this loss of funds. Another watcher can post an analogous proof of `d_3` against `deposit_merkle_root` to the fraud proof contracts that verify the proof and release another 32 ETH.

The fraud proof is just a merkle proof and the deposit data being proven. The fraud proof contract just verifies the merkle proof and makes sure that the proven deposit data is for public key that was later approved to deposit ETH from the Lido contracts by the Oracle. This makes Oracle fraud detectable on chain by solidifying that the Oracle certified a deposit to a validator whose withdrawal credentials were not pointed to the Lido contracts.

Does that clear things up at all?

---

<div class="post-metadata">

**Author:** ![ujenjt](https://dub1.discourse-cdn.com/flex013/user_avatar/research.lido.fi/ujenjt/32/240_2.png) [@ujenjt](https://research.lido.fi/u/ujenjt)\
**Post date:** [June 20, 2022, 8:31pm UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/4 "2022-06-20T20:31:27Z")

</div>

Yep, now it makes sense. The only issue is that BLS signatures are not so easily verifiable on-chain. I’ve seen [some implementations](https://ethresear.ch/t/bls-signatures-in-solidity/7919) but haven’t dived deep enough. If not to check the correctness of BLS signature, anyone could stop deposits by paying one ether and submit specially crafted deposit data to the deposit contract, which is not checks signatures.

---

<div class="post-metadata">

**Author:** ![bbuddha](https://avatars.discourse-cdn.com/v4/letter/b/13edae/32.png) [@bbuddha](https://research.lido.fi/u/bbuddha)\
**Post date:** [June 20, 2022, 9:59pm UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/5 "2022-06-20T21:59:20Z")

</div>

Ah, you’re totally right. Forgot that consensus layer uses BLS12-381 not bn254 which is what Ethereum precompiles support. The fraud proof probably doesn’t work then! 🙂

---

<div class="post-metadata">

**Author:** ![vsh](https://avatars.discourse-cdn.com/v4/letter/v/b19c9b/32.png) [@vsh](https://research.lido.fi/u/vsh)\
**Post date:** [June 21, 2022, 7:15am UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/6 "2022-06-21T07:15:29Z")

</div>

The other problem in this approach is that Lido bond is trivially griefed by a Lido operator (it’s not their bond, they lose nothing). It’s not a huge problem if the bonding + fraud proof was in addition to the current system, not instead of it.

---

<div class="post-metadata">

**Author:** ![vsh](https://avatars.discourse-cdn.com/v4/letter/v/b19c9b/32.png) [@vsh](https://research.lido.fi/u/vsh)\
**Post date:** [June 21, 2022, 7:17am UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/7 "2022-06-21T07:17:34Z")

</div>

I think if we’re putting that much effort into mitigation of the last drops of risk from deposits, it should on crafting a EIP to prevent this attack rather than running more epicycles around Lido. It’s more easily and cleanly solved on protocol side, to the benefit of the protocol.

---

<div class="post-metadata">

**Author:** ![ujenjt](https://dub1.discourse-cdn.com/flex013/user_avatar/research.lido.fi/ujenjt/32/240_2.png) [@ujenjt](https://research.lido.fi/u/ujenjt)\
**Post date:** [June 21, 2022, 8:20am UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/8 "2022-06-21T08:20:59Z")

</div>

+1 on this, the problem much more easily to fix on the protocol level

---

<div class="post-metadata">

**Author:** ![bbuddha](https://avatars.discourse-cdn.com/v4/letter/b/13edae/32.png) [@bbuddha](https://research.lido.fi/u/bbuddha)\
**Post date:** [June 21, 2022, 4:40pm UTC](https://research.lido.fi/t/optimistic-oracle-fraud-proofs-to-mitigate-consensus-layer-deposit-frontrunning/2452/9 "2022-06-21T16:40:26Z")

</div>

Could you elaborate a little on this point? To be clear I was suggesting the current oracle and fraud proofs.

Also, totally agree that the current deposit/withdrawal flow is really unintuitive and broken in some ways for the execution layer to interact with. This was a suggestion for reducing trust assumptions for stETH holders before execution layer is able to access beacon chain state. Maybe I’m overestimating how hard it is to get an EIP passed 🙂

Either way, implementing a elliptic curve pairing on BLS12-381 (needed for verifying BLS signatures) in Yul would probably lead to enormous gas costs and probably not make the upgrade worth it. Next time.
