HIGH severity: [FTN-2] Validator can add more than one contract. **Severity:** High

**Path:** beacon-chain/core/altair/deposit.go/ProcessDeposit(), beacon-chain/core/helpers/contracts.go/appendValidatorContractsWithVal()

**Description:** Function `ProcessDeposit()` is responsible for adding new validators and their contracts. This function calls function...

Vulnerable code:
func ProcessDeposit(beaconState state.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (state.BeaconState, bool, error) {
    var newValidator bool
    if err := verifyDeposit(beaconState, deposit); err != nil {
        if deposit == nil || deposit.Data == nil {
            return nil, newValidator, err
        }
        return nil, newValidator, errors.Wrapf(err, "could not verify deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey))
    }
    if err := beaconState.SetEth1DepositIndex(beaconState.Eth1DepositIndex() + 1); err != nil {
        return nil, newValidator, err
    }
    pubKey := deposit.Data.PublicKey
    amount := deposit.Data.Amount
    contract := deposit.Data.DeployedContract
    owner, contractExist := beaconState.ValidatorIndexByContractAddress(bytesutil.ToBytes20(contract))
    if contractExist {
        log.Debugf("Contract %x already regestered by validator %d. Register new validator with 0x0 contract address", contract, owner)
    }

    index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey))
    if !ok {
        if verifySignature {
            domain, err := signing.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
            if err != nil {
                return nil, newValidator, err
            }
            if err := verifyDepositDataSigningRoot(deposit.Data, domain); err != nil {
                // Ignore this error as in the spec pseudo code.
                log.WithError(err).Debug("Skipping deposit: could not verify deposit data signature")
                return beaconState, newValidator, nil
            }
        }

        effectiveBalance := amount - (amount % params.BeaconConfig().EffectiveBalanceIncrement)
        if params.BeaconConfig().MaxEffectiveBalance < effectiveBalance {
            effectiveBalance = params.BeaconConfig().MaxEffectiveBalance
        }
        if err := beaconState.AppendValidator(&ethpb.Validator{
            PublicKey:                  pubKey,
            WithdrawalCredentials:      deposit.Data.WithdrawalCredentials,
            ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch,
            ActivationEpoch:            params.BeaconConfig().FarFutureEpoch,
            ExitEpoch:                  params.BeaconConfig().FarFutureEpoch,
            WithdrawableEpoch:          params.BeaconConfig().FarFutureEpoch,
            EffectiveBalance:           effectiveBalance,
        }); err != nil {
            return nil, newValidator, err
        }
        newValidator = true
        if err := beaconState.AppendBalance(amount); err != nil {
            return nil, newValidator, err
        }
        if err := beaconState.AppendActivity(0); err != nil {
            return nil, newValidator, err
        }
        contracts := [][]byte{contract}
        if contractExist {
            contracts = [][]byte{make([]byte, 20)}
        }
        if err := beaconState.AppendContracts(&ethpb.ContractsContainer{
            Contracts: contracts,
        }); err != nil {
            return nil, newValidator, err
        }
    } else {
        if err := helpers.IncreaseBalance(beaconState, index, amount); err != nil {
            return nil, newValidator, err
        }
        if !contractExist && !isZeroContract(contract) {
            if err := helpers.AppendValidatorContracts(beaconState, index, contract); err != nil {
                return nil, newValidator, err
            }
        }
    }

    return beaconState, newValidator, nil
}

func appendValidatorContractsWithVal(cc *ethpb.ContractsContainer, contract []byte) *ethpb.ContractsContainer {
    contracts := cc.Contracts
    contracts = append(contracts, contract)
    cc.Contracts = contracts
    return cc
}