Creating Validators

🟢A Validator's Lifecycle

0.1. Create a pool - optional

It might take some time for other pools to give you an allowance.

It is best to create some pools to start testing immediately.

We will provide some Goerli Ether upon onboarding.

Create a basic pool easily:

Initiating a Customizable Staking Pool

Give Yourself allowance:

Managing Your Operator Set

0.2 Fund Your Wallet

Internal Wallet

Every ID has an Internal Wallet, which makes transferring Ether easier for both Geode's Portal, and it's users.

The Internal Wallet is the place where your fees will accrue over time.

Because of the bug explained here, you will need 1 Ether per validator proposal available in your internal wallet.

You will be reimbursed after activating the validator. However, this amount limits how many proposals you can have at the same time.

If you have 100 Ether in your internal wallet, and if it takes 1 day for proposals to be approved:

  • You can propose 100 validators a day.

await Portal.increaseWalletBalance(id, {value: 100 eth});

Check Your Wallet Balance

const balance = Portal.readUintForId(operatorId, getBytes("wallet"))

1. Pre-Proposal Checks

It is probably a good idea to initiate a couple staking pools and distribute your Goerli Funds among them, Someone else giving you allowance can take some time otherwise.

Get the list of all Staking Pools:

const all_pool_ids_list = Portal.allIdsByType(5, index);

Alternatively you can listen for OperatorApproval(indexed poolId,indexed yourId, amount);

Check Allowances

const allowance = Portal.readUintForId(

const proposedValidators = Portal.readUintForId(

const activeValidators = Portal.readUintForId(

You can create new validators if allowance is greater than proposedValidators + activeValidators.

Check Surplus

const surplus = Portal.readUintForId(poolId, getBytes("surplus"))

Every 32 ETH in surplus means 1 potential validator.

Join the Race

When enough funds are pooled for a new validator, you will need to be faster than the other Operators with enough allowance.

If you are the only Operator of the pool, you can take your time.

Otherwise, automate your tasks to be faster and capture the validator, or you will need to wait for another 32 Ether.

2. Proposing New Validators

Get withdrawalCredential

It is very important for you to use pool specific withdrawalCredentials in your validators. Otherwise, your proposal will not be approved!

await PORTAL.readAddressForId(

// or

await PORTAL.readBytesForId(

Staking Deposit Cli

We have forked the Ethereum's to add --amount parameter.

Using this CLI instead of the original one will allow you to customize the amount parameter:

git clone
cd staking-deposit-cli/
python3 -m pip3 install virtualenv
python3 -m virtualenv venv
source venv/bin/activate
python3 install
python3 -m pip3 install -r requirements.txt

Create deposit data

Call these

For signatures1:

  • create with a new-mnemonic OR use an existing mnemonic but be careful with validator index.

  • set --eth1_withdrawal_address to withdrawalContract

  • amount is 1

python3 ./staking_deposit/ new-mnemonic --num_validators=x --amount=1 --chain=prater --eth1_withdrawal_address 0xc82Ed5eC571673E6b18c4B092c9cbC4aE86C786e 

For signatures31:

  • use the same mnemonic while creating signatures1.

  • use the same validator index (0 if the same time).

  • specify the amount of validators with --num_validators

  • use the same --eth1_withdrawal_address

  • amount is 31

python ./staking_deposit/ existing-mnemonic --num_validators=x --amount=31 --mnemonic_language=english --chain=prater --eth1_withdrawal_address 0xc82Ed5eC571673E6b18c4B092c9cbC4aE86C786e
  • Pubkeys of the deposit data files should match.


    uint256 poolId,
    uint256 operatorId,
    bytes[] calldata pubkeys,
    bytes[] calldata signatures1,
    bytes[] calldata signatures31
  • signatures1: signature that will be used while proposing validators, sending 1 Ether to Deposit Contract.

  • signatures31: signature that will be used while activating validators, sending 31 Ether to Deposit Contract.

3. Check if You Can Stake for Your Proposal:

await Portal.canStake(pubkey);

It takes less than 24 hours for the Beacon Chain and our Oracle to verify a proposal.

4. Batch Validator Activation!

If your proposal is approved, you can use the pooled funds. However, you can save gas by doing Batch Activations:

Portal.beaconStake(uint256 operatorId, bytes[] calldata pubkeys);

Save gas cost:

Pub-keys should be arranged by pool ids.

For example: pub-keys = [pk1, pk2, pk3, pk4, pk5, pk6, pk7]

  • pk1, pk2, pk3 from pool1

  • pk4, pk5 from pool2

  • pk6 from pool3


Last updated