/// <summary>
        /// Decrease the validator balance at index ``index`` by ``delta``, with underflow protection.
        /// </summary>
        public void DecreaseBalance(BeaconState state, ValidatorIndex index, Gwei delta)
        {
            Gwei balance = state.Balances[(int)index];

            if (delta > balance)
            {
                state.SetBalance(index, Gwei.Zero);
            }
            else
            {
                Gwei newBalance = balance - delta;
                state.SetBalance(index, newBalance);
            }
        }
        /// <summary>
        /// Increase the validator balance at index ``index`` by ``delta``.
        /// </summary>
        public void IncreaseBalance(BeaconState state, ValidatorIndex index, Gwei delta)
        {
            Gwei balance    = state.Balances[(int)index];
            Gwei newBalance = balance + delta;

            state.SetBalance(index, newBalance);
        }
        public void EffectiveBalanceHysteresis()
        {
            // Arrange
            IServiceProvider testServiceProvider = TestSystem.BuildTestServiceProvider();
            BeaconState      state = TestState.PrepareTestState(testServiceProvider);

            //# Prepare state up to the final-updates.
            //# Then overwrite the balances, we only want to focus to be on the hysteresis based changes.
            TestProcessUtility.RunEpochProcessingTo(testServiceProvider, state, TestProcessStep.ProcessFinalUpdates);

            GweiValues gweiValues = testServiceProvider.GetService <IOptions <GweiValues> >().Value;

            BeaconChainUtility    beaconChainUtility    = testServiceProvider.GetService <BeaconChainUtility>();
            BeaconStateAccessor   beaconStateAccessor   = testServiceProvider.GetService <BeaconStateAccessor>();
            BeaconStateTransition beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>();

            // Set some edge cases for balances
            Gwei maximum       = gweiValues.MaximumEffectiveBalance;
            Gwei minimum       = gweiValues.EjectionBalance;
            Gwei increment     = gweiValues.EffectiveBalanceIncrement;
            Gwei halfIncrement = increment / 2;

            EffectiveBalanceCase[] testCases = new[] {
                new EffectiveBalanceCase(maximum, maximum, maximum, "as-is"),
                new EffectiveBalanceCase(maximum, (Gwei)(maximum - 1), maximum - increment, "round down, step lower"),
                new EffectiveBalanceCase(maximum, (Gwei)(maximum + 1), maximum, "round down"),
                new EffectiveBalanceCase(maximum, (Gwei)(maximum - increment), maximum - increment, "exactly 1 step lower"),
                new EffectiveBalanceCase(maximum, (Gwei)(maximum - increment - 1), maximum - (increment * 2), "just 1 over 1 step lower"),
                new EffectiveBalanceCase(maximum, (Gwei)(maximum - increment + 1), maximum - increment, "close to 1 step lower"),
                new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 3)), minimum, "bigger balance, but not high enough"),
                new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 3) + 1), minimum + increment, "bigger balance, high enough, but small step"),
                new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 4) - 1), minimum + increment, "bigger balance, high enough, close to double step"),
                new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 4)), minimum + (increment * 2), "exact two step balance increment"),
                new EffectiveBalanceCase(minimum, (Gwei)(minimum + (halfIncrement * 4) + 1), minimum + (increment * 2), "over two steps, round down"),
            };

            Epoch currentEpoch = beaconStateAccessor.GetCurrentEpoch(state);

            for (int index = 0; index < testCases.Length; index++)
            {
                Validator validator = state.Validators[index];
                bool      isActive  = beaconChainUtility.IsActiveValidator(validator, currentEpoch);
                isActive.ShouldBeTrue();

                EffectiveBalanceCase testCase = testCases[index];
                validator.SetEffectiveBalance(testCase.PreEffective);
                ValidatorIndex validatorIndex = new ValidatorIndex((ulong)index);
                state.SetBalance(validatorIndex, testCase.Balance);
            }

            // Act
            beaconStateTransition.ProcessFinalUpdates(state);

            // Assert
            for (int index = 0; index < testCases.Length; index++)
            {
                EffectiveBalanceCase testCase  = testCases[index];
                Validator            validator = state.Validators[index];
                validator.EffectiveBalance.ShouldBe(testCase.PostEffective, testCase.Name);
            }
        }