New Validator Creation

For setting up validators, P2P.ORG has introduced a new simplified smart contract flow — validators created this way receive the 0x02 type of withdrawal credentials. Compared to the previous 0x01 type, this brings the following benefits:

  • Flexible effective balance from 32 ETH up to 2048 ETH
  • New staking options such as incremental top-ups and auto compounding
  • Simplified flow with fewer steps and reduced manual deposit data handling

All changes are supported for both Ethereum and SSV staking APIs.

To upgrade to the 0x02 credentials type, you can either consolidate multiple existing validators into a single one or set up a new 0x02-enabled validator by following the steps below:

  1. Prepare a proxy staking transaction.
  2. Sign and broadcast the transaction.

Request examples are provided using cURL.

👍

Upgrade is just an option

For clients currently using the 0x01 validator setup, all existing endpoints remain supported. If you need to create a new validator via the previous 0x01 flow, refer to the guides for the Ethereum or SSV networks respectively.

Upgrading to the 0x02 type of withdrawal credentials is not necessary, but only recommended for enhanced functionality.

1. Prepare Staking Proxy Transaction

This flow is supported for Ethereum Direct staking only and applies exclusively to validators using 0x02 type of withdrawal credentials.

Send a GET request to /api/v1/eth/staking/direct/p2p/deposit with the following query parameters specified: amount, withdrawalAddress, controllerAddress and feeRecipientAddress.

By calling this endpoint, you are receiving a fully constructed by Ethereum Smart Contract 3.1 transaction which is ready for signing and broadcasting.

Example request:

curl --request GET \
  --url "https://api-test.p2p.org/api/v1/eth/staking/direct/p2p/deposit?amount=32&withdrawalAddress=0x8eB2277e54A2A7db9b7c0D9FA9B78dcB35f74866&controllerAddress=0x8eB2277e54A2A7db9b7c0D9FA9B78dcB35f74866&feeRecipientAddress=0x3202B5B0602274197CcB22B8c02CEC9539990c7c" \
  --header 'Authorization: Bearer <token>'
  
  • amount — total amount of ETH to deposit. Note that the maximum effective balance is 2048 ETH, so it is recommended specifying no more than 1920 ETH in order to save the opportunity to auto-compound the received rewards.
  • amountPerValidator — amount of tokens to stake in Gwei per validator.
  • withdrawalAddress — withdrawal address for the validators.
  • controllerAddresscontroller address for the validators.
  • feeRecipientAddress — address that receives priority fees.

Example response:

{
    "error": null,
    "result": {
        "serializeTx": "0x02f9025701808312c36c850727b59762839896809423be839a14cec3d6d716d904f09368bbf9c750eb8903782dace9d9000000b90224a49b131b0200000000000000000000008eb2277e54a2a7db9b7c0d9fa9b78dcb35f74866000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000003fcd8d9acac042095dfba53f4c40c74d19e2e9d9000000000000000000000000000000000000000000000000000000000000251c0000000000000000000000003202b5b0602274197ccb22b8c02cec9539990c7c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000e86b78000ed3b7b820ac6a39b46602356daee0602180fefa69a94774c3209a9f5ad1df42aa2c426b1494a39afc4ee79a528dca95807f5a1b518c8fb0a4df1be92b8a8b6e5f4fccf35f3975f9cf64aa92f4896f2553a5ba9fb0b13cabb25f21a2881f027d9703bfa57f45a514fff7bcc1b8020c2a3ab0581cfbb748dfe612a14acef40bc61de068cf3117e8227ab1315e0302f97e17d5b8948aa8071645b27ad74f669783d363fbc7e9dd58c01e535aff418b2fdbff56a55212e25efbc6b963bb048d98ecc1d03020f890bbf7518fd2463afb82ffdf452863268bdae4eae18d6108dce9ef803669f466000000000000000000000000000000000000000000000000c0",
        "to": "0x23BE839a14cEc3D6D716D904f09368Bbf9c750eb",
        "gasLimit": "10000000",
        "data": "0xa49b131b0200000000000000000000008eb2277e54a2a7db9b7c0d9fa9b78dcb35f74866000000000000000000000000000000000000000000000001bc16d674ec8000000000000000000000000000003fcd8d9acac042095dfba53f4c40c74d19e2e9d9000000000000000000000000000000000000000000000000000000000000251c0000000000000000000000003202b5b0602274197ccb22b8c02cec9539990c7c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000e86b78000ed3b7b820ac6a39b46602356daee0602180fefa69a94774c3209a9f5ad1df42aa2c426b1494a39afc4ee79a528dca95807f5a1b518c8fb0a4df1be92b8a8b6e5f4fccf35f3975f9cf64aa92f4896f2553a5ba9fb0b13cabb25f21a2881f027d9703bfa57f45a514fff7bcc1b8020c2a3ab0581cfbb748dfe612a14acef40bc61de068cf3117e8227ab1315e0302f97e17d5b8948aa8071645b27ad74f669783d363fbc7e9dd58c01e535aff418b2fdbff56a55212e25efbc6b963bb048d98ecc1d03020f890bbf7518fd2463afb82ffdf452863268bdae4eae18d6108dce9ef803669f466000000000000000000000000000000000000000000000000",
        "value": "64000000000000000000",
        "chainId": 1,
        "type": 2,
        "maxFeePerGas": "30730983266",
        "maxPriorityFeePerGas": "1229676"
    }
}
  • serializeTx — serialized unsigned transaction.
  • to — recipient address for this transaction.
  • gasLimit — maximum gas limit for this block.
  • data — transaction data.
  • value — amount this transaction is sending in Wei.
  • chainId — chain ID this transaction is authorized on, as specified by EIP-155.
  • typeEIP-2718 type of this transaction envelope.
  • maxFeePerGas — maximum price per unit of gas this transaction will pay for the combined EIP-1559 block's base fee and this transaction's priority fee in Wei.
  • maxPriorityFeePerGas — price per unit of gas in Wei, which is added to the EIP-1559 block's base fee. This added fee is used to incentivize miners to prioritize this transaction.

2. Sign and Broadcast Transaction

Prepare serializeTx from the previous step and use the example code below to sign and broadcast the transaction to the Ethereum network:

require("dotenv").config();
const ethers = require("ethers");

async function signAndBroadcast() {
  console.log("Started");

  // Enter the serialized transaction
  const rawTransaction = process.env.RAW_TRANSACTION;

  // Enter the private key of the address used to transfer the stake amount
  const privateKey = process.env.PRIVATE_KEY;

  // Enter the selected RPC URL
  const rpcURL = process.env.RPC_URL;

  // Initialize the provider using the RPC URL
  const provider = new ethers.providers.JsonRpcProvider(rpcURL);

  // Initialize a new Wallet instance
  const wallet = new ethers.Wallet(privateKey, provider);

  // Parse the raw transaction
  const tx = ethers.utils.parseTransaction(rawTransaction);

  tx.nonce = await provider.getTransactionCount(wallet.address);

  // Enter the max fee per gas and prirorty fee
  tx.maxFeePerGas = ethers.utils.parseUnits(
    process.env.MAX_FEE_PER_GAS_IN_GWEI,
    "gwei"
  );
  tx.maxPriorityFeePerGas = ethers.utils.parseUnits(
    process.env.MAX_PRIORITY_FEE_IN_GWEI,
    "gwei"
  );

  // Sign the transaction
  const signedTransaction = await wallet.signTransaction(tx);

  // Send the signed transaction
  const transactionResponse = await provider.sendTransaction(signedTransaction);

  return transactionResponse;
}

signAndBroadcast()
  .then((transactionResponse) => {
    console.log(
      "Transaction broadcasted, transaction hash:",
      transactionResponse.hash
    );
  })
  .catch((error) => {
    console.error("Error:", error);
  })
  .finally(() => {
    console.log("Finished");
  });

After the transaction is processed in the chain's queue, the new validator with 0x02 type of withdrawal credentials will be set up.