This library and collection of binaries are responsible for generating and uploading merkle roots to the on-chain tip-distribution program found here.
Each individual validator is assigned a new PDA per epoch where their share of tips, in lamports, will be stored. At the end of the epoch it's expected that validators take a commission and then distribute the rest of the funds to their delegators such that delegators receive rewards proportional to their respective delegations. The distribution mechanism is via merkle proofs similar to how airdrops work.
The merkle roots are calculated off-chain and uploaded to the validator's TipDistributionAccount PDA. Validators may elect an account to upload the merkle roots on their behalf. Once uploaded, users can invoke the claim instruction and receive the rewards they're entitled to. Once all funds are claimed by users the validator can close the account and refunded the rent.
This script generates a JSON file identifying individual stake delegations to a validator, along with amount of lamports in each validator's TipDistributionAccount. All validators will be contained in the JSON list, regardless of whether the validator is a participant in the system; participant being indicative of running the jito-solana client to accept tips having initialized a TipDistributionAccount PDA account for the epoch.
One edge case that we've taken into account is the last validator in an epoch N receives tips but those tips don't get transferred out into the PDA until some slot in epoch N + 1. Due to this we cannot rely on the bank's state at epoch N for lamports amount in the PDAs. We use the bank solely to take a snapshot of delegations, but an RPC node to fetch the PDA lamports for more up-to-date data.
This script accepts a path to the above JSON file as one of its arguments, and generates a merkle-root into a JSON file.
Uploads the root on-chain.
This reads the file outputted by merkle-root-generator
and finds all eligible accounts to receive mev tips. Transactions
are created and sent to the RPC server.
In order to use this library as the merkle root creator one must follow the following steps:
- Download a ledger snapshot containing the slot of interest, i.e. the last slot in an epoch. The Solana foundation has snapshots that can be found here.
- Download the snapshot onto your worker machine (where this script will run).
- Run
solana-ledger-tool -l ${PATH_TO_LEDGER} create-snapshot ${YOUR_SLOT} ${WHERE_TO_CREATE_SNAPSHOT}
- The snapshot created at
${WHERE_TO_CREATE_SNAPSHOT}
will have the highest slot of${YOUR_SLOT}
, assuming you downloaded the correct snapshot.
- The snapshot created at
- Run
stake-meta-generator --ledger-path ${WHERE_TO_CREATE_SNAPSHOT} --tip-distribution-program-id ${PUBKEY} --out-path ${JSON_OUT_PATH} --snapshot-slot ${SLOT} --rpc-url ${URL}
- Note:
${WHERE_TO_CREATE_SNAPSHOT}
must be the same in steps 3 & 4.
- Note:
- Run
merkle-root-generator --stake-meta-coll-path ${STAKE_META_COLLECTION_JSON} --rpc-url ${URL} --out-path ${MERKLE_ROOT_PATH}
- Run
merkle-root-uploader --out-path ${MERKLE_ROOT_PATH} --keypair-path ${KEYPAIR_PATH} --rpc-url ${URL} --tip-distribution-program-id ${PROGRAM_ID}
- Run
solana-claim-mev-tips --merkle-trees-path /solana/ledger/autosnapshot/merkle-tree-221615999.json --rpc-url ${URL} --tip-distribution-program-id ${PROGRAM_ID} --keypair-path ${KEYPAIR_PATH}
Voila!