6. Exit Daemon

Handling exit requests

As the channels can automatically select a number of validators that should be stopped, the "Exit Daemon" is here to signal the exit requests on a given vFactory.

This utility is a REST endpoint and also a webhook for the operators to automate exit flow of the validators.

📝 You will run one Exit Daemon for one vFactory

Running the Exit Daemon

You can find the exit daemon inside the operatord repository.


The daemon is configured using a config.yaml file, the same as the Oracle Daemon.

You have the option to either incorporate the following lines into a new configuration file or append them to the existing Oracle Daemon configuration file:

- service: "exit"
    factory: "0xcA43EFe1Ebde9AF74b5693bEACb2dfCC93cFc590"
    hook-endpoint: "http://localhost:9654/report"
  • factory: Address of the operator vFactory (mandatory).

  • hook-endpoint: REST endpoint that will be called (POST) when a report is available (optional).


Then, we can run the exit daemon by running:

docker run -it \
    -v ~/exit_data:/exit_data \
    ghcr.io/kilnfi/operatord:latest start-exit \
    --execution-node-url $ETHEREUM_RPC_URL \
    --consensus-node-url $BEACON_RPC_URL \
    --config-file /exit_data/operator.yml \
  • execution-node-url is an rpc endpoint on the execution layer (geth, erigon, etc...).

  • consensus-node-url is an rpc endpoint on the consensus layer (prysm, lighthouse, etc...).

  • config-file is the path to the file we configured above.


At every epoch (finalized), if exits are needed, the Exit Daemon craft a report for each withdrawal channel associated with the specified vFactory.

A report follows this JSON structure:

  "epoch": 187680,
  "withdrawalChannel": "0100000000000000000000000b226a56495872ad23a43130eae0bad248cc7aa1",
  "lastRequestTxHash": "584dbab6737f5b1a8aa75645555cb1b8953224d2b06800aab8f73eb6d9450f8b",
  "validatorCountToExit": 2,
  "totalCurrentlyExited": 1,
  "suggestedValidatorExits": [
      "publicKey": "99069f008d9807eb57fd4527af4da3fa821e19c1c382261309f7d7db3587a0f3ba28ac2b151709619034b8a18cf04d82",
      "index": 495139
      "publicKey": "ac4fa72a8acef9feb475c1225985b25f8cc4a01322f3360b5edcb9cd3a932b301dfb2a3b0cbd08344ce14f9ec7bc348e",
      "index": 495140
  "exitableValidators": [
      "publicKey": "85057a9a0ec28095bdf604ccfcf2ade3f8887938b05d987be8c8274021908aadab44d7dd7c214ac6ce576cd8b48b20ce",
      "index": 495924
      "publicKey": "ac95f5c11153eec413e687e03d61c3cc80ceaf1431434022a69cdd50b9147a2676a5d37665c08e0e446323273edb2f9c",
      "index": 495865
  • epoch: Epoch of the report

  • withdrawalChannel: Withdrawal channel id.

  • lastRequestTxHash: TX hash of the latest SetExitTotal event.

  • validatorCountToExit: Delta between the requested and actual exited validators.

  • totalCurrentlyExited: Total exited validators for the withdrawal channel.

  • suggestedValidatorExits: Lists suggested validators, providing their index and public key, that are eligible for exit. The suggested validators for exit are those with the oldest activationEpoch.

  • exitableValidators: Complete list of index / public Keys of all the currently exitable validators of the withdrawal channel.


The last (up to date) reports can be accessed using the REST API.

curl -X GET http://localhost:2020/reports | jq


Every epoch, the daemon has the capability to forward the reports to an endpoint.

As outlined in the configuration, you can specify a hook-endpoint in the configuration file. This endpoint will be triggered with a POST request when a report becomes available.

To illustrate its operation, we've created a demo server:

docker run -it \
    ghcr.io/kilnfi/operatord:latest start-demo-server \
    --endpoint $ENDPOINT \

The demo server accepts these reports and displays the corresponding JSON data in the terminal. It provides access to these reports via the /report route.

Last updated