Automated Ethereum Integration with Fireblocks
Let's integrate automated Ethereum staking using your Fireblocks custody solution.
This tutorial is made for mainnet integration, to test this in testnet first, you just need to add the testnet prefix to the urls (ex: ->


The goal is to propose to your clients an integrated Ethereum Staking experience in your platform. Here is an overview of what we are going to build:
Automated ETH staking integration using Fireblocks

Step 1 - Set up

  1. 1.
    Get your Kiln API token: head to your Kiln organization application page on the dashboard (link here) and create a new Application to get your API token.
  2. 2.
    Whitelist the Batch Deposit Contract on Fireblocks:
    a. Head to "Whitelisted Addresses"
    b. Click "+ Whitelisted wallet" button
    c. You can add a name like "Batch Deposit Contract"
    d. Then in the "Batch Deposit Contract" page you can click on "Add address" button
    e. Select Ethereum mainnet (or Goerli if you want the testnet version)
Example in testnet

Step 2 - Spin up validators on demand

  1. 1.
    Get the Account of your client: we recommend you keep a mapping in your database between your clients and Kiln Accounts (ex: create an Account A for client A), in order to make it easy for your to have an overview per client of the current stakes and rewards.
Create an Account inside an Organization
Get all Accounts of your Organization
2. Spin up validation keys for a selected Accound id: Specify the withdrawal_address (used to claim and receive the rewards) and the scoped Kiln Account id
curl -X POST \
-d '{"withdrawalAddress": "0xabc..."}' \
-H 'Content-Type: application/json' \
-H 'X-Kiln-Account': 'e9b46fcd-45dd-4782-9acb-7f3f3dcf551a'
"data": {
"pubkeys": ["..."],
"withdrawal_credentials": ["..."],
"signatures": ["..."],
"deposit_data_roots": ["..."]
In response, you will have the deposit data of the validator that was just spinned up for your client. We now need to make the deposit transaction with this deposit data to start the validator activation.

Step 3 - Make the deposit transaction

  1. 1.
    Craft the transaction for the batch deposit contract: here is an example with ethersjs on how to craft the raw transaction.
const { Contract, utils } = require('ethers');
// Contract info
const BATCH_DEPOSIT_ADDRESS = '0x9b8c989FF27e948F55B53Bb19B3cC1947852E394';
const BATCH_DEPOSIT_ABI = '[{"inputs":[{"internalType":"bytes[]","name":"pubkeys","type":"bytes[]"},{"internalType":"bytes[]","name":"withdrawal_credentials","type":"bytes[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"},{"internalType":"bytes32[]","name":"deposit_data_roots","type":"bytes32[]"}],"name":"batchDeposit","outputs":[],"stateMutability":"payable","type":"function","payable":true}]';
const batchContract = new Contract(BATCH_DEPOSIT_ADDRESS, BATCH_DEPOSIT_ABI);
// replace all XXX by the values returned by previous kiln api call
// Deposit parameters (every value must be prefixed with 0x)
const pubkeys = [XXX];
const withdrawal_credentials = [XXX];
const signatures = [XXX];
const deposit_data_roots = [utils.hexZeroPad(XXX, 32)];
// Generate raw transaction
const unsignedTx = await batchContract.populateTransaction.batchDeposit(pubkeys, withdrawal_credentials, signatures, deposit_data_roots);
console.log('rawTx:', utils.serializeTransaction(unsignedTx));
2. Send the transaction to Fireblocks raw signing API: use the POST /v1/transactions endpoint and send the the raw transaction data inside the extraParameters field.