Hello, I am Jade Han, a Security Researcher at Kalos Security.
Recently, while analyzing the Prysm Client Code, I investigated past vulnerability cases related to Ethereum 2.0 Staking.
As a result, I found a vulnerability that could occur during Ethereum 2.0 Staking with Tranchess, and reported it to the Tranchess team via Immunefi about two weeks ago.
In this article, I will briefly explain Tranchess and describe the vulnerability I reported.
Tranchess Liquid Staking is a staking service for Ethereum 2.0's Beacon Chain.
It allows users to stake their Ether to contribute to the stability of the Ethereum blockchain network and receive rewards in return.
Unlike traditional staking methods, Tranchess Liquid Staking tokenizes the staked assets to provide liquidity.
This allows users to have a token with a value equivalent to their staked assets that they can use whenever needed while also continuously receiving rewards.
To use this service, users must first deposit Ether into Tranchess Liquid Staking.
Tranchess then stakes the Ether to receive rewards from the Ethereum 2.0 network and pays a portion of these rewards to the user who deposited the Ether.
Tranchess tokenizes the deposited Ether into an ERC-20 token called qETH and provides it to the user.
Users can store qETH like any other ERC-20 token on an exchange or wallet and can exchange it back to Ether whenever needed.
In doing so, users can continuously receive staking rewards from the Ethereum 2.0 network.
The vulnerability I am going to explain in detail now occurs due to a structural problem between LSD and the outsourced node operator, as well as an issue with the Ethereum 2.0 Beacon client.
First, we need to understand the structure of the Liquid Staking Dapp before we can find this vulnerability.
I didn't know much about the structure of the Liquid Staking Dapp before looking for this vulnerability, and I thought the project team of the Liquid Staking Dapp operated nodes directly as Node Operators.
However, this was a misconception, and the Tranchess team did not operate the node directly.So, who receives the tokens through Tranchess, and who operates the node?The answer to that can be found in the link below.
Tranchess Partners RockX for ETH Liquid Staking
As described in the link above, Tranchess team does not operate the nodes directly but rather entrusts them to third parties to operate.
This is also the same structure for Tranchess's competitor, Lido.
I will now talk about the structure of the Ethereum 2.0 Beacon client.
With the transition to Ethereum 2.0, the Consensus Model of Ethereum has changed from PoW to PoS, and an official Deposit Contract (0x00000000219ab540356cBB839Cbe05303d7705Fa) has been introduced for staking.
below code is official Deposit contract code.
After calling the deposit function with the parameters pubkey, withdrawal_credentials, signature, and deposit_data_root, and the deposit is complete, a DepositEvent occurs.
Based on this event, the Ethereum 2.0 Beacon client (such as Prysm, Lighthouse, etc.) updates the staking state.
The following is the implementation code for the Prysm client.
Looking at the part that handles the Deposit Event, we can see that the balance in the Beacon state that reflects the Withdrawal credential set at the first deposit for a specific pubkey increases even if the Withdrawal credential changes for the second or third deposit.
Looking at the code, there is no error even if the withdrawal credential is different each time a deposit is made.
Considering the relationship between LSD and the outsourced node operator, the following scenarios can occur:
Although such scenarios can occur, Tranchess's EthStakingStrategy Contract had no mitigation for these malicious scenarios.
The following is the code for this:
Tranchess publicly uploaded these pubkeys to the NodeOperatorRegistry Contract, and the list is as follows:
There has been a similar type of vulnerability that occurred in the past.
It is described in the following link:
RocketPool and Lido Frontrunning Bugfix Review
Frax Ether Liquid Staking contest
The Tranchess team applied the mitigation created by Lido to their code.
The details are available in the link below.
lido-improvement-proposals/lip-5.md at develop · lidofinance/lido-improvement-proposals
Below is the history of the code they patched.
This Pull Request addresses a front-run vulnerability by restricting public access to certain functions and introducing a new contract called SafeStaking.
A trusted off-chain group verifies the pubkey used by Tranchess and provides signatures accordingly.
When the trusted off-chain group provides the signatures and submits them, the safeDeposit function checks the get_deposit_root, making it a secure code even if a malicious front-runner attempts front-running.
There is a different explanation for Mitigation attached to Tranchess Team's blog.
The link is provided below:
When creating an Ethereum 2.0 Liquid Staking Dapp, it is important to consider the structural issues with the Beacon chain client's implementation.
Previous examples such as Rocket Pool and Lido should be referenced, and it is important to have a good understanding of the implementation of Beacon chain clients such as Prysm, Lighthouse, etc.
This will help ensure that the Dapp is created with a secure and effective design.
Despite the bear market, I am grateful to Tranchess for paying me a large bug bounty.
We will continue to research other chains' Liquid Staking Security and hope to write another article with more achievements soon.Thank you for reading.