Suggested Fee Recipient

The fee recipient is an Ethereum address nominated by a beacon chain validator to receive tips from user transactions. Given that all mainnet and testnets have gone through The Merge, if you run validators on a network, you are strongly recommended to nominate a fee recipient for your validators. Failing to nominate a fee recipient will result in losing the tips from transactions.

Background

During post-merge block production, the Beacon Node (BN) will provide a suggested_fee_recipient to the execution node. This is a 20-byte Ethereum address which the execution node might choose to set as the recipient of other fees or rewards.

There is no guarantee that an execution node will use the suggested_fee_recipient to collect fees, it may use any address it chooses. It is assumed that an honest execution node will use the suggested_fee_recipient, but users should note this trust assumption.

The suggested_fee_recipient can be provided to the VC, which will transmit it to the BN. The BN also has a choice regarding the fee recipient it passes to the execution node, creating another noteworthy trust assumption.

To be sure you control your fee recipient value, run your own BN and execution node (don't use third-party services).

How to configure a suggested fee recipient

The Lighthouse VC provides two methods for setting the suggested_fee_recipient (also known simply as the "fee recipient") to be passed to the execution layer during block production. The Lighthouse BN also provides a method for defining this value, should the VC not transmit a value.

Assuming trustworthy nodes, the priority for the three methods is:

  1. validator_definitions.yml
  2. --suggested-fee-recipient provided to the VC.
  3. --suggested-fee-recipient provided to the BN.

NOTE: It is not recommended to only set the fee recipient on the beacon node, as this results in sub-optimal block proposals. See this issue for details.

1. Setting the fee recipient in the validator_definitions.yml

Users can set the fee recipient in validator_definitions.yml with the suggested_fee_recipient key. This option is recommended for most users, where each validator has a fixed fee recipient.

Below is an example of the validator_definitions.yml with suggested_fee_recipient values:

---
- enabled: true
  voting_public_key: "0x87a580d31d7bc69069b55f5a01995a610dd391a26dc9e36e81057a17211983a79266800ab8531f21f1083d7d84085007"
  type: local_keystore
  voting_keystore_path: /home/paul/.lighthouse/validators/0x87a580d31d7bc69069b55f5a01995a610dd391a26dc9e36e81057a17211983a79266800ab8531f21f1083d7d84085007/voting-keystore.json
  voting_keystore_password_path: /home/paul/.lighthouse/secrets/0x87a580d31d7bc69069b55f5a01995a610dd391a26dc9e36e81057a17211983a79266800ab8531f21f1083d7d84085007
  suggested_fee_recipient: "0x6cc8dcbca744a6e4ffedb98e1d0df903b10abd21"
- enabled: false
  voting_public_key: "0xa5566f9ec3c6e1fdf362634ebec9ef7aceb0e460e5079714808388e5d48f4ae1e12897fed1bea951c17fa389d511e477"
  type: local_keystore voting_keystore_path: /home/paul/.lighthouse/validators/0xa5566f9ec3c6e1fdf362634ebec9ef7aceb0e460e5079714808388e5d48f4ae1e12897fed1bea951c17fa389d511e477/voting-keystore.json
  voting_keystore_password: myStrongpa55word123&$
  suggested_fee_recipient: "0xa2e334e71511686bcfe38bb3ee1ad8f6babcc03d"

2. Using the "--suggested-fee-recipient" flag on the validator client

The --suggested-fee-recipient can be provided to the VC to act as a default value for all validators where a suggested_fee_recipient is not loaded from another method.

Provide a 0x-prefixed address, e.g.

lighthouse vc --suggested-fee-recipient 0x25c4a76E7d118705e7Ea2e9b7d8C59930d8aCD3b ...

3. Using the "--suggested-fee-recipient" flag on the beacon node

The --suggested-fee-recipient can be provided to the BN to act as a default value when the validator client does not transmit a suggested_fee_recipient to the BN.

lighthouse bn --suggested-fee-recipient 0x25c4a76E7d118705e7Ea2e9b7d8C59930d8aCD3b ...

This value should be considered an emergency fallback. You should set the fee recipient in the validator client in order for the execution node to be given adequate notice of block proposal.

Setting the fee recipient dynamically using the keymanager API

When the validator client API is enabled, the standard keymanager API includes an endpoint for setting the fee recipient dynamically for a given public key. When used, the fee recipient will be saved in validator_definitions.yml so that it persists across restarts of the validator client.

PropertySpecification
Path/eth/v1/validator/{pubkey}/feerecipient
MethodPOST
Required HeadersAuthorization
Typical Responses202, 404

Example Request Body

{
    "ethaddress": "0x1D4E51167DBDC4789a014357f4029ff76381b16c"
}

Command:

DATADIR=$HOME/.lighthouse/mainnet
PUBKEY=0xa9735061c84fc0003657e5bd38160762b7ef2d67d280e00347b1781570088c32c06f15418c144949f5d736b1d3a6c591
FEE_RECIPIENT=0x1D4E51167DBDC4789a014357f4029ff76381b16c

curl -X POST \
    -H "Authorization: Bearer $(cat ${DATADIR}/validators/api-token.txt)" \
    -H "Content-Type: application/json" \
    -d "{ \"ethaddress\": \"${FEE_RECIPIENT}\" }" \
    http://localhost:5062/eth/v1/validator/${PUBKEY}/feerecipient | jq

Note that an authorization header is required to interact with the API. This is specified with the header -H "Authorization: Bearer $(cat ${DATADIR}/validators/api-token.txt)" which read the API token to supply the authentication. Refer to Authorization Header for more information. If you are having permission issue with accessing the API token file, you can modify the header to become -H "Authorization: Bearer $(sudo cat ${DATADIR}/validators/api-token.txt)".

Successful Response (202)

null

A null response indicates that the request is successful.

Querying the fee recipient

The same path with a GET request can be used to query the fee recipient for a given public key at any time.

PropertySpecification
Path/eth/v1/validator/{pubkey}/feerecipient
MethodGET
Required HeadersAuthorization
Typical Responses200, 404

Command:

DATADIR=$HOME/.lighthouse/mainnet
PUBKEY=0xa9735061c84fc0003657e5bd38160762b7ef2d67d280e00347b1781570088c32c06f15418c144949f5d736b1d3a6c591

curl -X GET \
    -H "Authorization: Bearer $(cat ${DATADIR}/validators/api-token.txt)" \
    -H "Content-Type: application/json" \
    http://localhost:5062/eth/v1/validator/${PUBKEY}/feerecipient | jq

Successful Response (200)

{
  "data": {
    "pubkey": "0xa9735061c84fc0003657e5bd38160762b7ef2d67d280e00347b1781570088c32c06f15418c144949f5d736b1d3a6c591",
    "ethaddress": "0x1d4e51167dbdc4789a014357f4029ff76381b16c"
  }
}

Removing the fee recipient

The same path with a DELETE request can be used to remove the fee recipient for a given public key at any time. This is useful if you want the fee recipient to fall back to the validator client (or beacon node) default.

PropertySpecification
Path/eth/v1/validator/{pubkey}/feerecipient
MethodDELETE
Required HeadersAuthorization
Typical Responses204, 404

Command:

DATADIR=$HOME/.lighthouse/mainnet
PUBKEY=0xa9735061c84fc0003657e5bd38160762b7ef2d67d280e00347b1781570088c32c06f15418c144949f5d736b1d3a6c591

curl -X DELETE \
    -H "Authorization: Bearer $(cat ${DATADIR}/validators/api-token.txt)" \
    -H "Content-Type: application/json" \
    http://localhost:5062/eth/v1/validator/${PUBKEY}/feerecipient | jq

Successful Response (204)

null

FAQ

Why do I have to nominate an Ethereum address as the fee recipient?

You might wonder why the validator can't just accumulate transactions fees in the same way that it accumulates other staking rewards. The reason for this is that transaction fees are computed and validated by the execution node, and therefore need to be paid to an address that exists on the execution chain. Validators use BLS keys which do not correspond to Ethereum addresses, so they have no "presence" on the execution chain. Therefore, it's necessary for each validator to nominate a fee recipient address.