# Example: Validator Balance Data

In this example, the contract has a reference to the Telepathy [Light Client](https://docs.telepathy.xyz/telepathy-protocol/contracts#light-client) and uses the state root stored for a specific `slot`.&#x20;

Using a Merkle Proof, you can then verify that the data provided is correct for the that `slot`'s state root.

```solidity
contract BeaconValidatorBalance {
    uint256 public constant VALIDATOR_PUBKEY_GINDEX = 0;
    uint256 public constant BALANCE_G_INDEX = 1;

    address lightclient;
    mapping(uint256 => bytes32) public indexToPubkey;
    mapping(uint256 => mapping(uint256 => uint256)) public indexToSlotToBalance;

    constructor(address _lightclient) {
        lightclient = _lightclient;
    }

    function addIndexAndPubkey(
        uint256 slot, uint256 index, bytes32 publicKey, bytes32[] memory proof
    ) public {
        bytes32 headerRoot = ILightClient(lightclient).headers(slot);
        bool isValidProof = SSZ.verifyMerkleBranch(
            publicKey,
            concatGIndex(VALIDATOR_PUBKEY_GINDEX, index),
            proof,
            headerRoot
        );
        require(isValidProof, "Invalid state root");
        indexToPubkey[index] = publicKey;
    }

    function addBalanceAtSlot(uint256 slot, uint256 index, uint256 balance, bytes32[] memory proof) public {
        bytes32 headerRoot = ILightClient(lightclient).headers(slot);
        bool isValidProof = SSZ.verifyMerkleBranch(
            bytes32(balance),
            concatGIndex(BALANCE_G_INDEX, index),
            proof,
            headerRoot
        );
        require(isValidProof, "Invalid state root");
        indexToSlotToBalance[index][slot] = balance;
    }
}
```
