Synchronizes historical activity and performance of SSV validators and calculates their rewards according to Incentivized Mainnet Program.
git clone https://github.com/bloxapp/ssv-rewards
cd ssv-rewards
cp .env.example .env
cp rewards.example.yaml rewards.yaml
Edit .env
and fill in the required values:
# SSV network
NETWORK=mainnet
# Beacon API endpoint of the consensus node
CONSENSUS_ENDPOINT=http://beacon-node:5052
# JSON-RPC API endpoint of the execution node
EXECUTION_ENDPOINT=http://excution-node:8545
# SSV API endpoint
SSV_API_ENDPOINT=https://api.ssv.network/api/v4
# Beaconcha.in API
BEACONCHA_ENDPOINT=https://beaconcha.in
BEACONCHA_API_KEY= # Optional
BEACONCHA_REQUESTS_PER_MINUTE=20 # Adjust according to your Beaconcha.in API plan
# Etherscan API
ETHERSCAN_API_ENDPOINT=https://api.etherscan.io
ETHERSCAN_API_KEY= # Optional
ETHERSCAN_REQUESTS_PER_SECOND=0.1 # Adjust according to your Etherscan API plan
# Gnosis API
GNOSIS_API_ENDPOINT=https://safe-transaction-mainnet.safe.global
Edit rewards.yaml
to match the specifications:
version: 2
criteria:
min_attestations_per_day: 202
min_decideds_per_day: 22
mechanics:
- since: 2023-07
features:
tiers:
- max_participants: 2000 # Effective at up to 2,000 validators
apr_boost: 0.5 # Fraction of ETH APR to reward in SSV tokens
# ...
- max_participants: 30000
apr_boost: 0.1
- since: 2023-11
features:
# Rewards are paid to the owner address, unless it's a contract, in which case
# they are paid to the deployer address. Enabling gnosis_safe rewards the owner
# address despite it being a contract, when the contract is a Gnosis Safe.
- gnosis_safe
tiers:
- max_participants: 2000
apr_boost: 0.25
# ...
- max_participants: 30000
apr_boost: 0.05
# Redirect rewards to different addresses. The left-hand side is the owner address,
# and the right-hand side is the reward recipient address. Do not specify deployer
# addresses on the left-hand side, only owner addresses.
reward_redirects:
"0x1234567890abcdef1234567890abcdef12345678": "0x1234567890abcdef1234567890abcdef12345678"
rounds:
- period: 2023-07 # Designated period (year-month)
eth_apr: 0.047 # ETH Staking APR
ssv_eth: 0.0088235294 # SSV/ETH price
# ...
First, start PostgreSQL and wait a few seconds for it to be ready:
docker-compose up -d postgres
Synchronize validator activity and performance:
docker-compose run --rm sync
This should sync validator performance up until 2 days ago (UTC) or until the end of the last period in rewards.yaml
(whichever is lower). Therefore, in order to sync the last month, waiting until the 3rd of this month is required.
This might take a while, depending on how long ago the SSV contract was deployed and how many validators there are.
After syncing, you may calculate the reward distribution:
docker-compose run --rm calc
This produces the following documents under the ./rewards
directory:
📂 rewards
├── 📄 by-owner.csv # Reward for each owner for each round
├── 📄 by-validator.csv # Reward for each validator for each round
├── 📄 by-recipient.csv # Reward for each recipient for each round
├── 📄 total-by-owner.csv # Total reward for each owner
├── 📄 total-by-validator.csv # Total reward for each validator
└── 📂 <year>-<month>
├── 📄 by-owner.csv # Total reward for each owner for that round
├── 📄 by-validator.csv # Total reward for each validator for that round
├── 📄 by-recipient.csv # Total reward for each recipient for that round
└── 📄 cumulative.json # Cumulative reward for each owner until and including that round
recipient
is the address that eventually receives the reward, which is either the owner address, or if the owner is a contract, then the deployer address of the contract.
After calculating the reward distribution, you may merkleize the rewards for a specific round.
- Copy the file at
./rewards/<year>-<month>/cumulative.json
over to./scripts/merkle-generator/scripts/input_1.json
. - Run the merkleization script:
cd scripts/merkle-generator npm i npx hardhat run scripts/merkle.ts
- The merkle tree is generated at
./merkle-generator/scripts/output-1.json
.
- Pull the changes and rebuild the Docker images:
git pull docker-compose build
- Refer to
.env.example
and update your.env
file if necessary. - Refer to
rewards.example.yaml
and update yourrewards.yaml
file if necessary. - Sync with
--fresh
to re-create the databases and sync from scratch:docker-compose run --rm sync sync --fresh