# 4. Oracle Daemon

The next step would be to add an oracle member, and start using the Oracle Daemon with the oracle member private key to craft and send reports to the vPool.

By default, the pool expects at least two members before it can start operating, but Kiln runs the global oracle member, so adding one regular member will do the trick.

Remember, you can remove the global oracle member from your vPool only if you have at least 5 members in your oracle quorum, and if you toggle the ejection flag.

### Adding a new oracle member

The call is pretty simple, and should be performed by the vFactory admin

{% file src="<https://1911902555-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fnye3yqpuOzdfrtWAlwng%2Fuploads%2FDlsAiBhZpvjHTvxWoGne%2FvOracleAggregator.abi.json?alt=media&token=5ed1eb04-43dc-432a-b554-38804699e92c>" %}

<details>

<summary>TheGraph: Retrieve the vOracleAggregator address of the vPool</summary>

```graphql
{
  vFactories(where:{address:"YOUR_FACTORY_ADDRESS"}) {
    pools {
      address
      oracleAggregator {
        address
      }
    }
  }
}
```

```
{
  "data": {
    "vFactories": [
      {
        "pools": [
          {
            "address": "POOL_ADDRESS",
            "oracleAggregator": {
              "address": "ORACLE_AGGREGATOR_ADDRESS"
            }
          }
        ]
      }
    ]
  }
}
```

</details>

<details>

<summary>cast: Adding a new oracle member</summary>

`from=ADMIN`

```bash

cast send $ORACLE_AGGREGATOR_ADDRESS \
    "addMember(address)" \
    $ORACLE_MEMBER_ADDRESS \
    --rpc-url $ETH_RPC_URL

```

* You can add the `-i` flag to interactively provide the private key for the transaction
* You can add `--ledger --from YOUR_ADDRESS` to use a Ledger device to perform the transaction

</details>

<details>

<summary>TheGraph: Retrieve all the oracle members and the global member</summary>

```graphql
{
  vFactories(where:{address:"FACTORY_ADDRESS"}) {
    pools {
      oracleAggregator {
        members {
          address
        }
      }
    }
  }
  nexuses {
    globalOracle
  }
}
```

```
{
  "data": {
    "vFactories": [
      {
        "pools": [
          {
            "oracleAggregator": {
              "members": [
                {
                  "address": "THE_NEWLY_ADDED_MEMBER"
                }
              ]
            }
          }
        ]
      }
    ],
    "nexuses": [
      {
        "globalOracle": "GLOBAL_ORACLE_MEMBER"
      }
    ]
  }
}
```

</details>

### Running the Oracle Daemon

You can find the oracle daemon inside the `operatord` repository. It contains all the daemons that an operator might need to run.

#### Configuration

The oracle daemon is configured using a `config.yaml` file. Let's start by creating a directory for the oracle daemon:

```
mkdir ~/oracle_datadir
```

And then, create `~/oracle_datadir/config.yaml`, here's how it should look for one oracle member

```yaml
- service: "oracle"
  config:
    name: "oracle-member-0"
    private-key: "PRIVATE_KEY_IN_HEX"
    pool: "ADDRESS_OF_POOL"
    nexus: "ADDRESS_OF_NEXUS"
    purchase: true
    maxTxCostWei: "1000000000000000000"
```

* `name` is for logging purposes
* `private-key` is the private key of the member that you wish to run
* `pool` is the address of the `vPool` you wish to report for
* `nexus` is the address of the `Nexus` contract
* `purchase` is set to `true` if the member will also participate in performing the `purchaseValidators` call on the `vPool`
* `maxTxCostWei` is the maximum allowed cost of a tx in wei

#### Running using Docker

```bash
docker run -it \
    -v ~/oracle_data:/oracle_data \
    ghcr.io/kilnfi/operatord:latest start-oracle \
    --execution-node-url $ETHEREUM_RPC_URL \
    --consensus-node-url $BEACON_RPC_URL \
    --config-file /oracle_data/operator.yml \
    --database-file /oracle_data/oracle.db
```

It might take a bit of time to sync, but anything pulled from EL/CL that we'll need to reuse is stored inside the `sqlite` database that will be created. This would greatly speedup possible restarts.\
You should now ping Kiln to make sure that the global oracle member is running on their end. If that's the case, we should see oracle reports being posted

<details>

<summary>TheGraph: Get latest oracle report</summary>

```graphql
{
  vFactories(where:{address:"FACTORY_ADDRESS"}) {
    pools {
      reports(orderBy:epoch,orderDirection:desc,first:1) {
      	epoch
      	preSupply
      	postSupply
    	preUnderlyingSupply
     	postUnderlyingSupply
      	pulledCoverageFunds
      	pulledExecutionLayerRewards
      	pulledExitQueueUnclaimedFunds
    	consensusLayerDelta
      	rewards
      	exitFedEthers
      	newExitedEthers
      	newSkimmedEthers
      	activatedCount
      	stoppedCount
      	balanceSum
      	skimmedSum
      	exitedSum
      	exiting
      }
    }
  }
}
```

```
{
  "data": {
    "vFactories": [
      {
        "pools": [
          {
            "reports": [
              {
                "epoch": "185625",
                "preSupply": "640184161527309879390",
                "postSupply": "640184442079975696948",
                "preUnderlyingSupply": "641392925331000000000",
                "postUnderlyingSupply": "641395736166000000000",
                "pulledCoverageFunds": "0",
                "pulledExecutionLayerRewards": "0",
                "pulledExitQueueUnclaimedFunds": "0",
                "consensusLayerDelta": "2810835000000000",
                "revenue": "2810835000000000",
                "exitFedEthers": "0",
                "newExitedEthers": "0",
                "newSkimmedEthers": "0",
                "activatedCount": "20",
                "stoppedCount": "0",
                "balanceSum": "640004118170000000000",
                "skimmedSum": "341616994000000000",
                "exitedSum": "0",
                "exiting": "0"
              }
            ]
          }
        ]
      }
    ]
  }
}
```

</details>
