Validator’s Note 2 — An Analysis of Ethereum Effective Balance and Swell’s Guarded Launch Issue

Heejin Lee
DSRV
Published in
6 min readNov 24, 2022

Disclaimer: This article is for informational purposes only and should not be taken as financial advice. No information contained within this article is a recommendation to invest in any of the assets mentioned. All investors are advised to thoroughly conduct their own research before making any financial decisions.

While Swell is liquid staking platform similar to Lido or Rocket Pool, there are still a few differences worth pointing out. Swell is an open marketplace used by node operators. Node operators can adjust their commission rates, additional yield (i.e. MEV-boost), client types, etc. Stakers can then choose the most competitive node operator among the various options. Swell launched with 8 verified operators, including DSRV.

Compared to Lido and Rocket Pool with no minimum and a min of 0.01 ETH, respectively, Swell has a min of 1 ETH and stakers can deposit only in integer units. This is because Swell uses what’s known as ‘atomic deposits,’ which enable stakers to deposit directly to ETH deposit contracts [1]. Although a smaller minimum amount has its advantages, Swell‘s use of atomic deposits enhances transparency and security through fully non-custodial staking.

That being said, no one expected this new atomic deposit mechanism to trigger an edge case on Ethereum. So what exactly happened on Swell?

Swell: A breakdown of events

Usually a validator node is activated by depositing the required 32 ETH. However several validators having fulfilled this requirement were still not activating on the Beacon Chain, and hence were not able to begin attesting transactions and earning rewards.

After discussing with the Ethereum Foundation, Swell discovered that a rare edge case had occurred due to both the effective balance mechanism applied to Ethereum for security measures and its own atomic deposit system. In short, the validator effective balance was not calculated as the actual balance of 32 ETH, but instead required an additional deposit of 1 ETH to activate the validator [2].

Let’s take a closer look

Ethereum maintains a record of two separate validator balances, 1) the effective balance and 2) the actual balance. The actual balance refers to the amount of ETH that the validator node actually holds. This is subject to change every epoch due to rewards and penalties. The effective balance is used to calculate the rewards and penalties given to a validator. Validators are required to fulfill 32 ETH of the effective balance in order to activate.

The effective balance is calculated using the actual balance. To prevent attackers from updating the effective balance every epoch thereby slowing down on-chain processing, the effective balance is instead updated by a hysteresis formula and is rarely changed.

When the actual balance experiences change above a certain threshold, the effective balance is updated by rounding up or down the actual balance. For example, if the effective balance is n ETH and the actual balance drops to n-0.25 ETH, the effective balance is n-1 ETH. If the exact balance goes above n+1.25, the effective balance becomes n+1 ETH [3]. Additionally, if the exact balance goes to n+2 ETH, the effective balance is set to n+2 ETH.

As a result, if you deposit 32 ETH at once, the effective balance and the actual balance will both be set to 32 ETH. But if the effective balance increases incrementally, in some rare occasions, more than 32 ETH may be required to bring the effective balance up to 32 ETH.

Simulating Swell’s case with code

In order to further analyze this case, we simulated the non-activated node to study how the effective balance was changed.

(You can fork this code to simulate it yourself!)

In the case of a non-activated node, ETH was deposited in this order.

[1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1]

In this case, the effective balance was calculated to be 31 ETH, even though 32 ETH had actually been deposited. Before the final amount was deposited, the effective balance was 31 ETH. This means that the final amount should have been greater than 1.25 ETH in order to bring the effective balance up to 32 ETH. So Swell, which uses atomic deposits, had to deposit an additional 1 ETH to activate the validator node.

0  balance : 1 effective balance : 0
1 balance : 2 effective balance : 2
2 balance : 6 effective balance : 6
3 balance : 7 effective balance : 6
4 balance : 8 effective balance : 8
5 balance : 9 effective balance : 8
6 balance : 10 effective balance : 10
7 balance : 11 effective balance : 10
8 balance : 12 effective balance : 12
9 balance : 13 effective balance : 12
10 balance : 14 effective balance : 14
11 balance : 15 effective balance : 14
12 balance : 16 effective balance : 16
13 balance : 17 effective balance : 16
14 balance : 18 effective balance : 18
15 balance : 19 effective balance : 18
16 balance : 20 effective balance : 20
17 balance : 21 effective balance : 20
18 balance : 22 effective balance : 22
19 balance : 23 effective balance : 22
20 balance : 24 effective balance : 24
21 balance : 25 effective balance : 24
22 balance : 26 effective balance : 26
23 balance : 27 effective balance : 26
24 balance : 28 effective balance : 28
25 balance : 31 effective balance : 31
26 balance : 32 effective balance : 31

In the case of the successfully activated DSRV node, the effective balance reached 32 ETH. So what was different? ETH was deposited in this order:

 [1, 1, 1, 2, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 10, 1, 1, 1, 1]

Before the last amount was deposited, the effective balance was 30 ETH and the actual balance 31 ETH. After the last deposit, since the actual balance was increased by 2, the effective balance was successfully updated to 32 ETH. As you can see in this case, it doesn’t matter if the last deposited amount is over 1 ETH. But if the last deposited amount is 1 ETH, the amount right before that last deposit should also be 1 ETH.

deposits = []int{1, 1, 1, 2, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 10, 1, 1, 1, 1}


0 balance : 1 effective balance : 0
1 balance : 2 effective balance : 2
2 balance : 3 effective balance : 2
3 balance : 5 effective balance : 5
4 balance : 6 effective balance : 5
5 balance : 7 effective balance : 7
6 balance : 8 effective balance : 7
7 balance : 11 effective balance : 11
8 balance : 12 effective balance : 11
9 balance : 13 effective balance : 13
10 balance : 14 effective balance : 13
11 balance : 15 effective balance : 15
12 balance : 16 effective balance : 15
13 balance : 17 effective balance : 17
14 balance : 18 effective balance : 17
15 balance : 28 effective balance : 28
16 balance : 29 effective balance : 28
17 balance : 30 effective balance : 30
18 balance : 31 effective balance : 30
19 balance : 32 effective balance : 32

Conclusion

Although Swell has reported this issue to the EF, it may still take a while to resolve as it’s considered to be minor [4][5]. So Swell is working on its own solution to ensure it can continue the Guarded Launch in spite of the Beacon Chain bug. The staking service has been temporarily suspended for now, but will be resumed after contract upgrade. The Swell team announced that the architecture will be changed, and that staking deposits will be reopened in the new year [6].

Written by
Heejin Lee, Software Engineer and Validator, DSRV Validator Team (Twitter @heeheejin)

Edited by
Youngbin Park, Research Engineer, DSRV Validator Team (Twitter@bin0_0bin)

Reviewed by
Domitille Colin, Brand Communications Manager (Twitter @domitille_marie)

References
[1] https://github.com/ethereum/consensus-specs/blob/dev/solidity_deposit_contract/deposit_contract.sol#L112-L116
[2] https://blog.swellnetwork.io/swell-network-guarded-launch-update/
[3] https://notes.ethereum.org/@vbuterin/SkeyEI3xv#Misc
[4] https://github.com/ethereum/consensus-specs/issues/3049
[5] https://github.com/ethereum/consensus-specs/pull/3045
[6] https://blog.swellnetwork.io/swell-network-architecture-upgrade/

--

--