From 65dcbdd6689452c4c0e63ba561ab87a132e75cd4 Mon Sep 17 00:00:00 2001 From: Pablo Maldonado Date: Wed, 29 Apr 2026 16:14:14 +0000 Subject: [PATCH 1/5] fix(gas-rebates): add VotingV2 correction audit --- packages/affiliates/.gitignore | 6 + .../gas-rebate/AuditVoterGasRebateV2.ts | 61 + packages/affiliates/gas-rebate/README.md | 168 +- .../affiliates/gas-rebate/VoterGasRebateV2.ts | 215 +- .../gas-rebate/voterGasRebateV2Utils.ts | 1795 +++++++++++++++++ .../gas-rebate/VoterGasRebateV2Utils.js | 954 +++++++++ 6 files changed, 3033 insertions(+), 166 deletions(-) create mode 100644 packages/affiliates/gas-rebate/AuditVoterGasRebateV2.ts create mode 100644 packages/affiliates/gas-rebate/voterGasRebateV2Utils.ts create mode 100644 packages/affiliates/test/mocha-local/gas-rebate/VoterGasRebateV2Utils.js diff --git a/packages/affiliates/.gitignore b/packages/affiliates/.gitignore index de153db3b7..0b9c57490a 100644 --- a/packages/affiliates/.gitignore +++ b/packages/affiliates/.gitignore @@ -1 +1,7 @@ artifacts + +# Generated gas rebate audit JSON can be very large. Keep manifests, payout JSON, +# and audit Markdown review summaries commit-ready, but leave detailed audit JSON +# as a local/regenerable artifact. +gas-rebate/rebates/*.audit.json +gas-rebate/corrections/*.audit.json diff --git a/packages/affiliates/gas-rebate/AuditVoterGasRebateV2.ts b/packages/affiliates/gas-rebate/AuditVoterGasRebateV2.ts new file mode 100644 index 0000000000..7587ee6af3 --- /dev/null +++ b/packages/affiliates/gas-rebate/AuditVoterGasRebateV2.ts @@ -0,0 +1,61 @@ +// VotingV2-only correction audit script. It recomputes paid rebate files from a manifest, +// diffs exact wei amounts, and writes a consolidated positive top-up payout. + +import "@nomiclabs/hardhat-ethers"; +import { getAddress } from "@uma/contracts-node"; +import type { VotingV2 } from "@uma/contracts-node/dist/packages/contracts-node/typechain/core/ethers/VotingV2"; +import hre from "hardhat"; +import path from "path"; +import { runVotingV2CorrectionAudit } from "./voterGasRebateV2Utils"; + +const { AUDIT_MANIFEST, OUTPUT_DIR, ALLOW_OVERWRITE, MAX_RETRIES, RETRY_DELAY, CUSTOM_NODE_URL } = process.env; + +function requireEnvironmentVariable(value: string | undefined, name: string): string { + if (!value || value.trim() === "") { + throw new Error(`${name} is required for VotingV2 correction audit mode`); + } + return value; +} + +export async function run(): Promise { + requireEnvironmentVariable(CUSTOM_NODE_URL, "CUSTOM_NODE_URL"); + const manifestPath = path.resolve(process.cwd(), requireEnvironmentVariable(AUDIT_MANIFEST, "AUDIT_MANIFEST")); + const outputDir = OUTPUT_DIR + ? path.resolve(process.cwd(), OUTPUT_DIR) + : path.resolve(process.cwd(), "gas-rebate/corrections"); + const expectedVotingV2Address = await getAddress("VotingV2", 1); + const voting = (await hre.ethers.getContractAt("VotingV2", expectedVotingV2Address)) as VotingV2; + const retryConfig = { + retries: MAX_RETRIES ? Number(MAX_RETRIES) : 10, + delay: RETRY_DELAY ? Number(RETRY_DELAY) : 1000, + }; + + console.log("Running VotingV2 gas rebate correction audit"); + console.log("Manifest:", manifestPath); + console.log("Output directory:", outputDir); + console.log("Overwrite enabled:", ALLOW_OVERWRITE === "true"); + + const written = await runVotingV2CorrectionAudit({ + manifestPath, + voting, + outputDir, + expectedVotingContractAddress: expectedVotingV2Address, + baseDir: process.cwd(), + allowOverwrite: ALLOW_OVERWRITE === "true", + customNodeUrlConfigured: true, + retryConfig, + }); + + console.log("Correction payout JSON written to", written.payoutPath); + console.log("Correction audit JSON written to", written.auditJsonPath); + console.log("Correction audit Markdown written to", written.auditMarkdownPath); +} + +if (require.main === module) { + run() + .then(() => process.exit(0)) + .catch(async (error) => { + console.log("error", error); + process.exit(1); + }); +} diff --git a/packages/affiliates/gas-rebate/README.md b/packages/affiliates/gas-rebate/README.md index 120db11a9d..4fd58aa3e8 100644 --- a/packages/affiliates/gas-rebate/README.md +++ b/packages/affiliates/gas-rebate/README.md @@ -9,31 +9,37 @@ The main script for calculating gas rebates for UMA 2.0 voters. It finds all `Vo ### How It Works 1. Determines the previous month's date range (designed to run monthly) -2. Fetches all `VoteCommitted` and `VoteRevealed` events from the VotingV2 contract +2. Fetches all `VoteCommitted` and `VoteRevealed` events from the VotingV2 contract in small block chunks 3. Filters out voters with less than the minimum staked tokens 4. Deduplicates commit events (only the first commit per voter per round is refunded) 5. Matches commit events with corresponding reveal events -6. Calculates gas rebates (with optional priority fee cap) -7. Saves results to `rebates/Rebate_.json` +6. Validates discovered event transactions against receipt logs and splits failed ranges before accepting results +7. Calculates gas rebates (with optional priority fee cap) +8. Saves results to `rebates/Rebate_.json` plus audit reports ### Usage +Use an operator-provided RPC URL for production runs. Do not commit RPC keys, concrete RPC URLs, shell history, or copied commands containing provider credentials. Monthly mode can warn when `CUSTOM_NODE_URL` is not configured; correction/audit mode requires it. + ```bash # Run from the affiliates package directory cd packages/affiliates -# Basic usage (uses defaults, calculates for previous month) -yarn hardhat run gas-rebate/VoterGasRebateV2.ts --network mainnet +# Normal monthly run for the previous month +CUSTOM_NODE_URL="" \ +yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet # With custom configuration +CUSTOM_NODE_URL="" \ OVERRIDE_FROM_BLOCK=18000000 \ OVERRIDE_TO_BLOCK=18500000 \ MIN_STAKED_TOKENS=1000 \ -yarn hardhat run gas-rebate/VoterGasRebateV2.ts --network mainnet +yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet # With priority fee cap (optional) +CUSTOM_NODE_URL="" \ MAX_PRIORITY_FEE_GWEI=0.001 \ -yarn hardhat run gas-rebate/VoterGasRebateV2.ts --network mainnet +yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet ``` ### Environment Variables @@ -44,11 +50,35 @@ yarn hardhat run gas-rebate/VoterGasRebateV2.ts --network mainnet | `OVERRIDE_TO_BLOCK` | End block number (overrides automatic date-based calculation) | Auto-calculated from previous month end | | `MIN_STAKED_TOKENS` | Minimum UMA tokens staked to be eligible for rebate | `500` | | `MAX_PRIORITY_FEE_GWEI` | Maximum priority fee to refund (in gwei). If not set, no cap is applied. | None (no cap) | -| `MAX_BLOCK_LOOK_BACK` | Maximum block range for paginated event queries | `20000` | +| `MAX_BLOCK_LOOK_BACK` | Maximum block range for VotingV2 event queries | `250` | | `TRANSACTION_CONCURRENCY` | Number of concurrent RPC requests for fetching transactions/blocks | `50` | | `MAX_RETRIES` | Maximum retry attempts for failed RPC calls | `10` | | `RETRY_DELAY` | Delay between retries in milliseconds | `1000` | +### Safe Chunk Size and Validation + +`MAX_BLOCK_LOOK_BACK=250` is the safe default chunk size for VotingV2 rebate runs. The smaller default reduces the chance that a provider silently truncates `eth_getLogs` responses on high-event ranges. The script also validates discovered VotingV2 event transactions against receipt logs and adaptively splits ranges when validation detects missing `VoteCommitted` or `VoteRevealed` logs. + +Do not raise `MAX_BLOCK_LOOK_BACK` for production payouts unless the audit report still shows validation passed and the retry/split/anomaly output is understood by the reviewer. If validation fails, the script fails closed and should not produce payout artifacts. + +### March 2026 Rebate 66 Rerun + +The March 2026 recompute uses the original paid Rebate 66 block range and policy parameters. Replace only the placeholder RPC URL: + +```bash +cd packages/affiliates + +CUSTOM_NODE_URL="" \ +NODE_OPTIONS="--max-old-space-size=24000" \ +OVERRIDE_FROM_BLOCK=24558868 \ +OVERRIDE_TO_BLOCK=24781026 \ +MIN_STAKED_TOKENS=1000 \ +TRANSACTION_CONCURRENCY=100 \ +MAX_BLOCK_LOOK_BACK=250 \ +MAX_PRIORITY_FEE_GWEI=0.001 \ +yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet +``` + ### Output Format The script outputs a JSON file to `rebates/Rebate_.json` with the following structure: @@ -78,6 +108,128 @@ The script outputs a JSON file to `rebates/Rebate_.json` with the following s | `totalRebateAmount` | Total ETH amount to be rebated | | `shareholderPayout` | Map of voter addresses to their rebate amounts (in ETH) | +### Monthly Audit Reports + +Each successful monthly run also writes: + +- `rebates/Rebate_.audit.json` +- `rebates/Rebate_.audit.md` + +The audit JSON contains the exact payout total in wei, transaction-level evidence, the effective configuration, block range, event counts, eligible reveal count, matched commit count, transaction count, voter count, event collector stats, validation status, and anomalies. The Markdown report is a concise reviewer summary generated from the same audit object. + +Audit JSON files can be very large and are ignored by git. Keep them as local/regenerable evidence unless a reviewer explicitly asks for one to be attached out-of-band. Commit the payout JSON, manifest, and audit Markdown summary. + +Reviewers should confirm that event collection validation passed, retry/split counts look reasonable for the RPC provider used, anomalies are understood, and the payout JSON matches the audited total before approving payment. + +## AuditVoterGasRebateV2.ts + +Correction/audit mode is VotingV2-only. Do not use this script for the legacy UMA 1.0 `VoterGasRebate.js` workflow. + +The correction audit script recomputes one or more paid VotingV2 rebate files from a manifest and writes a consolidated top-up payout for positive deltas only. Historical `Rebate_*.json` files are immutable paid records and must not be edited to correct a prior payout. Negative deltas are reported in the audit output but excluded from the payout JSON. + +Run from `packages/affiliates`: + +```bash +CUSTOM_NODE_URL="" \ +AUDIT_MANIFEST=gas-rebate/corrections/.json \ +yarn hardhat run ./gas-rebate/AuditVoterGasRebateV2.ts --network mainnet +``` + +Required environment variables: + +| Variable | Description | +| ----------------- | ----------------------------------------------------------------------- | +| `CUSTOM_NODE_URL` | Explicit mainnet RPC URL for correction/audit mode | +| `AUDIT_MANIFEST` | Correction manifest path, relative to `packages/affiliates` or absolute | + +Optional environment variables: + +| Variable | Description | Default | +| ----------------- | ---------------------------------------------------- | ------------------------ | +| `OUTPUT_DIR` | Directory for correction payout and audit artifacts | `gas-rebate/corrections` | +| `ALLOW_OVERWRITE` | Set to `true` to replace existing correction outputs | `false` | +| `MAX_RETRIES` | Maximum retry attempts for failed RPC calls | `10` | +| `RETRY_DELAY` | Delay between retries in milliseconds | `1000` | + +Manifest entries must specify the paid rebate file, rebate number, block range, VotingV2 contract, original min-stake and priority-fee policy, block chunk size, transaction concurrency, and any exact `expectedDeltas` that must be enforced. The script fails before writing outputs when the manifest or paid file schema is invalid, paid files are missing, block ranges overlap, a non-VotingV2 contract is configured, an expected delta does not match exactly, or an output artifact already exists without `ALLOW_OVERWRITE=true`. + +### Correction Manifest Schema + +Manifests are committed under `gas-rebate/corrections/` and must not contain secrets: + +```json +{ + "version": 1, + "name": "March 2026 Rebate 66 VotingV2 correction", + "votingContractAddress": "0x004395edb43EFca9885CEdad51EC9fAf93Bd34ac", + "outputPrefix": "Correction_Rebate_66", + "audits": [ + { + "rebateFile": "gas-rebate/rebates/Rebate_66.json", + "rebateNumber": 66, + "fromBlock": 24558868, + "toBlock": 24781026, + "minStakedTokens": "1000", + "maxPriorityFeeGwei": "0.001", + "maxBlockLookBack": 250, + "transactionConcurrency": 100, + "notes": "March 2026 VotingV2 rebate recomputation" + } + ], + "expectedDeltas": [ + { + "rebateNumber": 66, + "address": "0xf20737e48160a87Dc9D1B26D8B63c796d2F1eA91", + "deltaWei": "7088051537280779" + }, + { + "rebateNumber": 66, + "address": "0x2a9437DE0cCD4FD7b7D98831213AcedeFC7a1092", + "deltaWei": "1902006430166225" + } + ] +} +``` + +For older rebate audits, preserve each paid file's original `fromBlock`, `toBlock`, `minStakedTokens`, `maxPriorityFeeGwei`, `maxBlockLookBack`, and `transactionConcurrency`. Do not apply March 2026 parameters to other rebate files unless those were their original policy parameters. + +### March 2026 Correction Audit + +Run the committed Rebate 66 correction manifest with an operator-provided RPC URL: + +```bash +cd packages/affiliates + +CUSTOM_NODE_URL="" \ +NODE_OPTIONS="--max-old-space-size=24000" \ +AUDIT_MANIFEST=gas-rebate/corrections/Rebate_66_Correction_Manifest.json \ +yarn hardhat run ./gas-rebate/AuditVoterGasRebateV2.ts --network mainnet +``` + +The script writes `Correction_Rebate_66.json`, `Correction_Rebate_66.audit.json`, and `Correction_Rebate_66.audit.md` under `gas-rebate/corrections/` unless `OUTPUT_DIR` changes the destination. The `.audit.json` file is intentionally git-ignored because it can contain large transaction-level evidence; commit the correction payout JSON and `.audit.md` reviewer summary. + +### Overpayments + +Overpayments are not clawed back by this workflow. Report zero and negative deltas in the correction audit, exclude negative deltas from the make-good payout, and escalate for an explicit product or governance decision if a future clawback or netting approach is requested. + +### Artifact Review Checklist + +- Event collection validation passed for every audited rebate. +- Expected deltas pass exactly, including the March 2026 Rebate 66 checks when that manifest is used. +- Generated payout total equals the positive top-up total in the audit Markdown summary or local audit JSON. +- Correction payout includes only positive deltas; zero and negative deltas are report-only. +- Audit Markdown references the intended manifest, paid files, block ranges, and policy parameters. Keep the larger audit JSON local unless explicitly requested. +- No historical `Rebate_*.json` file was modified. +- No RPC key, concrete RPC URL, `.env` value, or shell history was committed. + +### PR Checklist + +- No secrets committed. +- Expected deltas pass. +- Validation passed. +- Generated payout total equals audit summary total. +- Historical rebates unchanged. + ### Priority Fee Capping (Optional) By default, the script rebates the full gas cost including any priority fee. You can optionally cap the priority fee (tip) portion to prevent rebating excessive tips by setting `MAX_PRIORITY_FEE_GWEI`. diff --git a/packages/affiliates/gas-rebate/VoterGasRebateV2.ts b/packages/affiliates/gas-rebate/VoterGasRebateV2.ts index f8441b8c94..b096deee80 100644 --- a/packages/affiliates/gas-rebate/VoterGasRebateV2.ts +++ b/packages/affiliates/gas-rebate/VoterGasRebateV2.ts @@ -4,20 +4,15 @@ // used in UMA tokens. The script aggregates the gas rebates by voter and saves the results to a file. // It is designed // to not require any run time parameters by always running it one month after the desired output month. -import { TransactionReceipt } from "@ethersproject/abstract-provider"; import "@nomiclabs/hardhat-ethers"; -import { findBlockNumberAtTimestamp, getWeb3, paginatedEventQuery } from "@uma/common"; +import { findBlockNumberAtTimestamp, getWeb3 } from "@uma/common"; import { getAddress } from "@uma/contracts-node"; -import { - VoteCommittedEvent, - VoteRevealedEvent, -} from "@uma/contracts-node/dist/packages/contracts-node/typechain/core/ethers/VotingV2"; -import Bluebird from "bluebird"; -import { BigNumber, Event } from "ethers"; +import type { VotingV2 } from "@uma/contracts-node/dist/packages/contracts-node/typechain/core/ethers/VotingV2"; import fs from "fs"; import hre from "hardhat"; import moment from "moment"; import path from "path"; +import { calculateVoterGasRebateV2, writeMonthlyAuditReports } from "./voterGasRebateV2Utils"; const { ethers } = hre; const { @@ -31,27 +26,6 @@ const { MAX_BLOCK_LOOK_BACK, } = process.env; -async function retryAsyncOperation( - operation: () => Promise, - retries = MAX_RETRIES ? Number(MAX_RETRIES) : 10, - delay = RETRY_DELAY ? Number(RETRY_DELAY) : 1000 -): Promise { - let attempt = 0; - while (attempt < retries) { - try { - return await operation(); - } catch (error) { - attempt++; - if (attempt < retries) { - await new Promise((resolve) => setTimeout(resolve, delay)); - } else { - throw new Error(`Operation failed after ${retries} attempts: ${error}`); - } - } - } - throw new Error("This should never be reached"); -} - export async function run(): Promise { console.log("Running UMA2.0 Gas rebate script! This script assumes you are running it for the previous month๐ŸŒ."); @@ -79,158 +53,69 @@ export async function run(): Promise { // Minimum UMA tokens staked to be eligible for a rebate const minTokens = ethers.utils.parseEther(MIN_STAKED_TOKENS ? MIN_STAKED_TOKENS : "500"); + const maxPriorityFee = MAX_PRIORITY_FEE_GWEI ? ethers.utils.parseUnits(MAX_PRIORITY_FEE_GWEI, "gwei") : null; + const maxBlockLookBack = MAX_BLOCK_LOOK_BACK ? Number(MAX_BLOCK_LOOK_BACK) : 250; + const retryConfig = { + retries: MAX_RETRIES ? Number(MAX_RETRIES) : 10, + delay: RETRY_DELAY ? Number(RETRY_DELAY) : 1000, + }; console.log("Minimum UMA tokens staked to be eligible for a rebate:", ethers.utils.formatEther(minTokens)); console.log("Current time:", moment(currentDate).format()); console.log("Previous Month Start:", moment(prevMonthStart).format(), "& block", fromBlock); console.log("Previous Month End:", moment(prevMonthEnd).format(), "& block", toBlock); + console.log("Gas rebate V2 config:", { + fromBlock, + toBlock, + minStakedTokens: ethers.utils.formatEther(minTokens), + maxPriorityFeeGwei: maxPriorityFee ? ethers.utils.formatUnits(maxPriorityFee, "gwei") : null, + maxBlockLookBack, + transactionConcurrency, + }); // Fetch all commit and reveal events. - const voting = await hre.ethers.getContractAt("VotingV2", await getAddress("VotingV2", 1)); + const voting = (await hre.ethers.getContractAt("VotingV2", await getAddress("VotingV2", 1))) as VotingV2; - const maxBlockLookBack = MAX_BLOCK_LOOK_BACK ? Number(MAX_BLOCK_LOOK_BACK) : 20000; - const searchConfig = { + const rebateComputation = await calculateVoterGasRebateV2({ + voting, fromBlock, toBlock, + minTokens, maxBlockLookBack, - }; - - // Find resolved events - const commitEvents = await paginatedEventQuery( - voting, - voting.filters.VoteCommitted(), - searchConfig - ); - const revealEvents = await paginatedEventQuery( - voting, - voting.filters.VoteRevealed(), - searchConfig - ); - - // Filter out events with less than the minimum UMA tokens staked - const revealEventsMinBalance = revealEvents.filter((event) => event.args.numTokens.gte(minTokens)); - - // Filter out duplicate commit events as we only refund the first commit event per voter per round - const uniqueCommitEvents = new Map(); - - // Sort first by blockNumber (asc) and then by logIndex (asc) as a tiebreaker - const sortedCommitEvents = commitEvents.sort((a, b) => { - if (a.blockNumber !== b.blockNumber) { - return a.blockNumber - b.blockNumber; // Sort by blockNumber (asc) - } - return a.logIndex - b.logIndex; // Sort by logIndex (asc) within the same block + transactionConcurrency, + maxPriorityFee, + retryConfig, }); - for (const event of sortedCommitEvents) { - const key = `${event.args.voter}-${event.args.roundId}-${event.args.identifier}-${event.args.time}-${event.args.ancillaryData}`; - if (!uniqueCommitEvents.has(key)) { - uniqueCommitEvents.set(key, event); - } - } - // Filter out commit events that don't have a corresponding reveal event - const matchingCommitEvents = revealEventsMinBalance - .map((event) => - uniqueCommitEvents.get( - `${event.args.voter}-${event.args.roundId}-${event.args.identifier}-${event.args.time}-${event.args.ancillaryData}` - ) - ) - .filter((event) => event !== undefined); - - // For each event find the associated transaction. We want to refund all transactions that were sent by voters. - // Function to process events sequentially - const getTransactionsFromEvents = async (events: Event[]) => { - const transactions = await Bluebird.map( - events, - async (event) => { - return await retryAsyncOperation( - async () => await voting.provider.getTransactionReceipt(event.transactionHash) - ); - }, - { concurrency: transactionConcurrency } - ); - return transactions; - }; - - const commitTransactions = await getTransactionsFromEvents(matchingCommitEvents); - const revealTransactions = await getTransactionsFromEvents(revealEventsMinBalance); - - // The transactions to refund are the union of the commit and reveal transactions. We need to remove any duplicates - // as a voter could have done multiple commits and reveals in the same transaction due to multicall. If we refund - // the full gas used within a transaction then we will refund for all commit-reveal operations within that tx. - const transactionsToRefund = [...commitTransactions, ...revealTransactions].reduce( - (accumulator: TransactionReceipt[], current) => { - if (!accumulator.find((transaction) => transaction.transactionHash === current.transactionHash)) - accumulator.push(current); - - return accumulator; - }, - [] - ); + console.log("VotingV2 event collection stats:", rebateComputation.eventCollectionStats); + if (rebateComputation.anomalies.length > 0) { + console.log("VotingV2 event collection anomalies:", rebateComputation.anomalies); + } console.log( - `In aggregate, refund ${commitEvents.length} commits and ${revealEvents.length} Reveals` + - ` for a total of ${transactionsToRefund.length} transactions` + `In aggregate, refund ${rebateComputation.commitEvents.length} commits and ` + + `${rebateComputation.revealEvents.length} Reveals for a total of ` + + `${rebateComputation.transactionsToRefund.length} transactions` ); - // Max priority fee to refund (optional - if not set, no cap is applied) - const maxPriorityFee = MAX_PRIORITY_FEE_GWEI ? ethers.utils.parseUnits(MAX_PRIORITY_FEE_GWEI, "gwei") : null; if (maxPriorityFee) { console.log("Max priority fee to refund:", ethers.utils.formatUnits(maxPriorityFee, "gwei"), "gwei"); } else { console.log("No priority fee cap applied"); } - // Get unique block numbers from transactions to fetch block data - const uniqueBlockNumbers = [...new Set(transactionsToRefund.map((tx) => tx.blockNumber))]; - console.log(`Fetching base fee data for ${uniqueBlockNumbers.length} unique blocks...`); - - // Fetch block data in parallel to get base fees - const blockDataMap = new Map(); - await Bluebird.map( - uniqueBlockNumbers, - async (blockNumber) => { - const block = await retryAsyncOperation(async () => await voting.provider.getBlock(blockNumber)); - if (block.baseFeePerGas) { - blockDataMap.set(blockNumber, block.baseFeePerGas); - } - }, - { concurrency: transactionConcurrency } - ); - - const shareholderPayoutBN: { [address: string]: BigNumber } = {}; - // Now, traverse all transactions and calculate the rebate for each. - for (const transaction of transactionsToRefund) { - const baseFee = blockDataMap.get(transaction.blockNumber); - let effectiveGasPriceForRebate: BigNumber; - - if (baseFee) { - // Calculate the actual priority fee paid - const actualPriorityFee = transaction.effectiveGasPrice.sub(baseFee); - // Cap the priority fee at maxPriorityFee if set - const cappedPriorityFee = - maxPriorityFee && actualPriorityFee.gt(maxPriorityFee) ? maxPriorityFee : actualPriorityFee; - // Rebate = gasUsed * (baseFee + cappedPriorityFee) - effectiveGasPriceForRebate = baseFee.add(cappedPriorityFee); - } else { - // Fallback for pre-EIP-1559 transactions (shouldn't happen on mainnet post-London) - effectiveGasPriceForRebate = transaction.effectiveGasPrice; - } - - const resultantRebate = transaction.gasUsed.mul(effectiveGasPriceForRebate); - // Save the output to the shareholderPayout object. Append to existing value if it exists. - if (!shareholderPayoutBN[transaction.from]) shareholderPayoutBN[transaction.from] = BigNumber.from(0); - shareholderPayoutBN[transaction.from] = shareholderPayoutBN[transaction.from].add(resultantRebate); - } - // Create a formatted output that is not bignumbers. const shareholderPayout: { [key: string]: number } = {}; - for (const [key, value] of Object.entries(shareholderPayoutBN)) + for (const [key, value] of Object.entries(rebateComputation.shareholderPayoutWei)) shareholderPayout[key] = parseFloat(ethers.utils.formatEther(value)); // Now save the output. First, work out the next rebate number by looking at previous rebate files. const basePath = `${path.resolve(__dirname)}/rebates/`; const rebates = fs.readdirSync(basePath); - const previousRebates = rebates.map((f) => parseInt(f.substring(f.indexOf("_") + 1, f.indexOf(".")))); + const previousRebates = rebates + .map((fileName) => fileName.match(/^Rebate_(\d+)\.json$/)) + .filter((match): match is RegExpMatchArray => match !== null) + .map((match) => parseInt(match[1], 10)); const rebateNumber = Math.max.apply(null, previousRebates) + 1; console.log("The next rebate number is", rebateNumber); @@ -241,18 +126,32 @@ export async function run(): Promise { fromBlock, toBlock, countVoters: Object.keys(shareholderPayout).length, - totalRebateAmount: parseFloat( - ethers.utils.formatEther( - Object.values(shareholderPayoutBN) - .reduce((a, b) => a.add(b), BigNumber.from(0)) - .toString() - ) - ), + totalRebateAmount: parseFloat(ethers.utils.formatEther(rebateComputation.totalRebateWei.toString())), shareholderPayout, }; const savePath = `${path.resolve(__dirname)}/rebates/Rebate_${rebateNumber}.json`; fs.writeFileSync(savePath, JSON.stringify(finalOutputObject, null, 4)); console.log("๐Ÿ—„ File successfully written to", savePath); + + const auditReports = writeMonthlyAuditReports(rebateComputation, { + outputRebateFilePath: savePath, + rebateNumber, + config: { + minStakedTokens: ethers.utils.formatEther(minTokens), + minStakedTokensWei: minTokens.toString(), + maxPriorityFeeGwei: maxPriorityFee ? ethers.utils.formatUnits(maxPriorityFee, "gwei") : null, + maxPriorityFeeWei: maxPriorityFee ? maxPriorityFee.toString() : null, + maxBlockLookBack, + transactionConcurrency, + maxRetries: retryConfig.retries, + retryDelay: retryConfig.delay, + overrideFromBlockConfigured: Boolean(OVERRIDE_FROM_BLOCK), + overrideToBlockConfigured: Boolean(OVERRIDE_TO_BLOCK), + customNodeUrlConfigured: Boolean(process.env.CUSTOM_NODE_URL), + }, + }); + console.log("Monthly audit JSON written to", auditReports.jsonPath); + console.log("Monthly audit Markdown written to", auditReports.markdownPath); } if (require.main === module) { diff --git a/packages/affiliates/gas-rebate/voterGasRebateV2Utils.ts b/packages/affiliates/gas-rebate/voterGasRebateV2Utils.ts new file mode 100644 index 0000000000..65ae86c2d1 --- /dev/null +++ b/packages/affiliates/gas-rebate/voterGasRebateV2Utils.ts @@ -0,0 +1,1795 @@ +import type { TransactionReceipt } from "@ethersproject/abstract-provider"; +import type { + VoteCommittedEvent, + VoteRevealedEvent, + VotingV2, +} from "@uma/contracts-node/dist/packages/contracts-node/typechain/core/ethers/VotingV2"; +import Bluebird from "bluebird"; +import { createHash } from "crypto"; +import { BigNumber, Event, utils } from "ethers"; +import fs from "fs"; +import path from "path"; + +export interface RetryConfig { + retries?: number; + delay?: number; +} + +export interface CalculateVoterGasRebateV2Config { + voting: VotingV2; + fromBlock: number; + toBlock: number; + minTokens: BigNumber; + maxBlockLookBack: number; + transactionConcurrency: number; + maxPriorityFee: BigNumber | null; + retryConfig?: RetryConfig; +} + +export interface RebateTransactionEvidence { + transactionHash: string; + from: string; + blockNumber: number; + gasUsed: string; + effectiveGasPrice: string; + baseFee: string | null; + actualPriorityFee: string | null; + cappedPriorityFee: string | null; + effectiveGasPriceForRebate: string; + rebateWei: string; +} + +export type RebateAnomalyType = + | "reveal_missing_commit" + | "missing_receipt" + | "receipt_event_count_mismatch" + | "provider_error"; + +export interface RebateAnomaly { + type: RebateAnomalyType; + message: string; + fromBlock?: number; + toBlock?: number; + transactionHash?: string; + voter?: string; + details?: { [key: string]: string | number | null }; +} + +export interface EventCollectionStats { + maxBlockLookBack: number; + minBlockLookBack: number; + rangesQueried: number; + queryAttempts: number; + retryCount: number; + splitCount: number; + validationFailures: number; + providerErrors: number; + receiptValidationCount: number; + commitEventCount: number; + revealEventCount: number; + validationPassed: boolean; +} + +export interface RebateComputationResult { + votingContractAddress: string; + fromBlock: number; + toBlock: number; + minStakedTokens: BigNumber; + maxBlockLookBack: number; + transactionConcurrency: number; + maxPriorityFee: BigNumber | null; + commitEvents: VoteCommittedEvent[]; + revealEvents: VoteRevealedEvent[]; + eligibleRevealEvents: VoteRevealedEvent[]; + matchingCommitEvents: VoteCommittedEvent[]; + transactionsToRefund: TransactionReceipt[]; + shareholderPayoutWei: { [address: string]: BigNumber }; + totalRebateWei: BigNumber; + transactionEvidence: RebateTransactionEvidence[]; + eventCollectionStats: EventCollectionStats; + anomalies: RebateAnomaly[]; +} + +export interface MonthlyAuditReportConfig { + minStakedTokens: string; + minStakedTokensWei: string; + maxPriorityFeeGwei: string | null; + maxPriorityFeeWei: string | null; + maxBlockLookBack: number; + transactionConcurrency: number; + maxRetries: number; + retryDelay: number; + overrideFromBlockConfigured: boolean; + overrideToBlockConfigured: boolean; + customNodeUrlConfigured: boolean; +} + +export interface MonthlyAuditReportOptions { + outputRebateFilePath: string; + rebateNumber: number; + config: MonthlyAuditReportConfig; + generatedAt?: string; +} + +export interface MonthlyAuditReport { + reportType: "VotingV2MonthlyGasRebateAudit"; + generatedAt: string; + outputRebateFilePath: string; + rebateNumber: number; + votingContractAddress: string; + blockRange: { + fromBlock: number; + toBlock: number; + }; + effectiveConfig: MonthlyAuditReportConfig; + counts: { + commitEvents: number; + revealEvents: number; + eligibleRevealEvents: number; + matchedCommitEvents: number; + transactions: number; + voters: number; + }; + payout: { + totalRebateWei: string; + totalRebateEth: string; + }; + eventCollection: EventCollectionStats; + validation: { + passed: boolean; + anomalyCount: number; + }; + anomalies: RebateAnomaly[]; + transactionEvidence: RebateTransactionEvidence[]; +} + +export interface MonthlyAuditReportPaths { + jsonPath: string; + markdownPath: string; +} + +export interface WrittenMonthlyAuditReports extends MonthlyAuditReportPaths { + report: MonthlyAuditReport; +} + +export interface CorrectionManifestAuditEntry { + rebateFile: string; + rebateNumber: number; + fromBlock: number; + toBlock: number; + minStakedTokens: string; + maxPriorityFeeGwei: string | null; + maxBlockLookBack: number; + transactionConcurrency: number; + notes?: string; +} + +export interface CorrectionExpectedDelta { + rebateNumber: number; + address: string; + deltaWei: string; +} + +export interface CorrectionManifest { + version: 1; + name: string; + votingContractAddress: string; + outputPrefix: string; + audits: CorrectionManifestAuditEntry[]; + expectedDeltas: CorrectionExpectedDelta[]; +} + +export interface PaidRebateFile { + votingContractAddress: string; + rebate: number; + fromBlock: number; + toBlock: number; + countVoters: number; + totalRebateAmount: number | string; + shareholderPayout: { [address: string]: number | string }; +} + +export interface ValidatedCorrectionManifestAuditEntry extends CorrectionManifestAuditEntry { + paidRebateFilePath: string; + paidRebate: PaidRebateFile; + minStakedTokensWei: string; + maxPriorityFeeWei: string | null; +} + +export interface ValidatedCorrectionManifest extends Omit { + audits: ValidatedCorrectionManifestAuditEntry[]; + expectedDeltas: CorrectionExpectedDelta[]; +} + +export interface CorrectionAddressDelta { + address: string; + paidWei: string; + recomputedWei: string; + deltaWei: string; +} + +export interface CorrectionExpectedDeltaCheck { + rebateNumber: number; + address: string; + expectedDeltaWei: string; + actualDeltaWei: string; + passed: boolean; +} + +export interface CorrectionAuditRebateReport { + rebateNumber: number; + rebateFile: string; + paidRebateFilePath: string; + notes?: string; + blockRange: { + fromBlock: number; + toBlock: number; + }; + effectiveConfig: { + minStakedTokens: string; + minStakedTokensWei: string; + maxPriorityFeeGwei: string | null; + maxPriorityFeeWei: string | null; + maxBlockLookBack: number; + transactionConcurrency: number; + maxRetries: number | null; + retryDelay: number | null; + }; + paid: { + countVoters: number; + totalRebateWei: string; + totalRebateEth: string; + }; + recomputed: { + countVoters: number; + totalRebateWei: string; + totalRebateEth: string; + }; + deltas: { + positive: CorrectionAddressDelta[]; + zero: CorrectionAddressDelta[]; + negative: CorrectionAddressDelta[]; + positiveTotalWei: string; + positiveTotalEth: string; + negativeTotalWei: string; + negativeTotalEth: string; + }; + eventCollection: EventCollectionStats; + anomalies: RebateAnomaly[]; + transactionEvidenceForPositiveDeltas: RebateTransactionEvidence[]; +} + +export interface CorrectionPayoutJson { + votingContractAddress: string; + rebate: number; + fromBlock: number; + toBlock: number; + countVoters: number; + totalRebateAmount: number; + shareholderPayout: { [address: string]: number }; +} + +export interface CorrectionAuditReport { + reportType: "VotingV2GasRebateCorrectionAudit"; + generatedAt: string; + manifestPath: string; + manifestHash: string; + manifestName: string; + outputPrefix: string; + outputPaths: CorrectionArtifactPaths; + votingContractAddress: string; + customNodeUrlConfigured: boolean; + validation: { + passed: boolean; + expectedDeltaChecksPassed: boolean; + negativeDeltaCount: number; + anomalyCount: number; + }; + auditedRebates: CorrectionAuditRebateReport[]; + expectedDeltaChecks: CorrectionExpectedDeltaCheck[]; + consolidatedTopUp: { + countVoters: number; + totalWei: string; + totalEth: string; + shareholderPayoutWei: { [address: string]: string }; + }; +} + +export interface CorrectionArtifactPaths { + payoutPath: string; + auditJsonPath: string; + auditMarkdownPath: string; +} + +export interface WrittenCorrectionArtifacts extends CorrectionArtifactPaths { + payout: CorrectionPayoutJson; + report: CorrectionAuditReport; +} + +export type CorrectionRebateCalculator = ( + config: CalculateVoterGasRebateV2Config, + entry: ValidatedCorrectionManifestAuditEntry, + manifest: ValidatedCorrectionManifest +) => Promise; + +export interface RunVotingV2CorrectionAuditOptions { + manifestPath: string; + voting: VotingV2; + outputDir: string; + expectedVotingContractAddress?: string; + baseDir?: string; + allowOverwrite?: boolean; + customNodeUrlConfigured?: boolean; + retryConfig?: RetryConfig; + generatedAt?: string; + calculateRebate?: CorrectionRebateCalculator; +} + +interface CollectedVotingEvents { + commitEvents: VoteCommittedEvent[]; + revealEvents: VoteRevealedEvent[]; + receiptByTransactionHash: Map; + eventCollectionStats: EventCollectionStats; + anomalies: RebateAnomaly[]; +} + +interface CollectedRangeEvents { + commitEvents: VoteCommittedEvent[]; + revealEvents: VoteRevealedEvent[]; +} + +interface TransactionEventCounts { + commit: number; + reveal: number; +} + +export class EventCollectionValidationError extends Error { + public readonly eventCollectionStats: EventCollectionStats; + public readonly anomalies: RebateAnomaly[]; + + constructor(message: string, eventCollectionStats: EventCollectionStats, anomalies: RebateAnomaly[]) { + super(message); + this.name = "EventCollectionValidationError"; + this.eventCollectionStats = eventCollectionStats; + this.anomalies = anomalies; + } +} + +export class CorrectionManifestValidationError extends Error { + constructor(message: string) { + super(message); + this.name = "CorrectionManifestValidationError"; + } +} + +export function getMonthlyAuditReportPaths(outputRebateFilePath: string): MonthlyAuditReportPaths { + const parsedPath = path.parse(outputRebateFilePath); + return { + jsonPath: path.join(parsedPath.dir, `${parsedPath.name}.audit.json`), + markdownPath: path.join(parsedPath.dir, `${parsedPath.name}.audit.md`), + }; +} + +export function buildMonthlyAuditReport( + result: RebateComputationResult, + { outputRebateFilePath, rebateNumber, config, generatedAt }: MonthlyAuditReportOptions +): MonthlyAuditReport { + return { + reportType: "VotingV2MonthlyGasRebateAudit", + generatedAt: generatedAt || new Date().toISOString(), + outputRebateFilePath, + rebateNumber, + votingContractAddress: result.votingContractAddress, + blockRange: { + fromBlock: result.fromBlock, + toBlock: result.toBlock, + }, + effectiveConfig: { + ...config, + }, + counts: { + commitEvents: result.commitEvents.length, + revealEvents: result.revealEvents.length, + eligibleRevealEvents: result.eligibleRevealEvents.length, + matchedCommitEvents: result.matchingCommitEvents.length, + transactions: result.transactionsToRefund.length, + voters: Object.keys(result.shareholderPayoutWei).length, + }, + payout: { + totalRebateWei: result.totalRebateWei.toString(), + totalRebateEth: utils.formatEther(result.totalRebateWei), + }, + eventCollection: { + ...result.eventCollectionStats, + }, + validation: { + passed: result.eventCollectionStats.validationPassed, + anomalyCount: result.anomalies.length, + }, + anomalies: result.anomalies, + transactionEvidence: result.transactionEvidence, + }; +} + +export function formatMonthlyAuditMarkdown(report: MonthlyAuditReport): string { + const config = report.effectiveConfig; + const collection = report.eventCollection; + const anomalyLines = + report.anomalies.length === 0 + ? ["- None"] + : report.anomalies.map((anomaly) => { + const location = + anomaly.fromBlock !== undefined && anomaly.toBlock !== undefined + ? ` (${anomaly.fromBlock}-${anomaly.toBlock})` + : ""; + const transaction = anomaly.transactionHash ? ` tx ${anomaly.transactionHash}` : ""; + return `- ${anomaly.type}${location}${transaction}: ${anomaly.message}`; + }); + + return [ + `# VotingV2 Monthly Gas Rebate Audit - Rebate ${report.rebateNumber}`, + "", + `Generated at: ${report.generatedAt}`, + `Output rebate file: \`${report.outputRebateFilePath}\``, + `VotingV2 contract: \`${report.votingContractAddress}\``, + `Block range: ${report.blockRange.fromBlock}-${report.blockRange.toBlock}`, + "", + "## Effective Config", + "", + `- Minimum staked tokens: ${config.minStakedTokens} UMA (${config.minStakedTokensWei} wei)`, + `- Max priority fee: ${config.maxPriorityFeeGwei === null ? "none" : `${config.maxPriorityFeeGwei} gwei`}`, + `- Max block lookback: ${config.maxBlockLookBack}`, + `- Transaction concurrency: ${config.transactionConcurrency}`, + `- Max retries: ${config.maxRetries}`, + `- Retry delay: ${config.retryDelay} ms`, + `- Override from block configured: ${config.overrideFromBlockConfigured}`, + `- Override to block configured: ${config.overrideToBlockConfigured}`, + `- Custom node URL configured: ${config.customNodeUrlConfigured}`, + "", + "## Summary", + "", + `- Commit events: ${report.counts.commitEvents}`, + `- Reveal events: ${report.counts.revealEvents}`, + `- Eligible reveal events: ${report.counts.eligibleRevealEvents}`, + `- Matched commit events: ${report.counts.matchedCommitEvents}`, + `- Transactions: ${report.counts.transactions}`, + `- Voters: ${report.counts.voters}`, + `- Total payout: ${report.payout.totalRebateWei} wei (${report.payout.totalRebateEth} ETH)`, + "", + "## Event Collection", + "", + `- Validation passed: ${report.validation.passed}`, + `- Chunk size: ${collection.maxBlockLookBack}`, + `- Ranges queried: ${collection.rangesQueried}`, + `- Query attempts: ${collection.queryAttempts}`, + `- Retry count: ${collection.retryCount}`, + `- Split count: ${collection.splitCount}`, + `- Validation failures: ${collection.validationFailures}`, + `- Provider errors: ${collection.providerErrors}`, + `- Receipt validations: ${collection.receiptValidationCount}`, + "", + "## Anomalies", + "", + ...anomalyLines, + "", + ].join("\n"); +} + +export function writeMonthlyAuditReports( + result: RebateComputationResult, + options: MonthlyAuditReportOptions +): WrittenMonthlyAuditReports { + const report = buildMonthlyAuditReport(result, options); + const { jsonPath, markdownPath } = getMonthlyAuditReportPaths(options.outputRebateFilePath); + + fs.writeFileSync(jsonPath, JSON.stringify(report, null, 4)); + fs.writeFileSync(markdownPath, formatMonthlyAuditMarkdown(report)); + + return { + jsonPath, + markdownPath, + report, + }; +} + +export async function retryAsyncOperation( + operation: () => Promise, + retries = 10, + delay = 1000, + onFailure?: (error: unknown, attempt: number, willRetry: boolean) => void +): Promise { + let attempt = 0; + const maxAttempts = Math.max(1, retries); + + while (attempt < maxAttempts) { + try { + return await operation(); + } catch (error) { + attempt++; + const willRetry = attempt < maxAttempts; + if (onFailure) onFailure(error, attempt, willRetry); + + if (willRetry) { + await new Promise((resolve) => setTimeout(resolve, delay)); + } else { + throw new Error(`Operation failed after ${maxAttempts} attempts: ${error}`); + } + } + } + throw new Error("This should never be reached"); +} + +export function sortEventsByBlockAndLogIndex>(events: T[]): T[] { + return [...events].sort((a, b) => { + if (a.blockNumber !== b.blockNumber) return a.blockNumber - b.blockNumber; + return a.logIndex - b.logIndex; + }); +} + +function getVoteKey(event: VoteCommittedEvent | VoteRevealedEvent): string { + return `${event.args.voter}-${event.args.roundId}-${event.args.identifier}-${event.args.time}-${event.args.ancillaryData}`; +} + +export function getUniqueCommitEvents(commitEvents: VoteCommittedEvent[]): Map { + const uniqueCommitEvents = new Map(); + + for (const event of sortEventsByBlockAndLogIndex(commitEvents)) { + const key = getVoteKey(event); + if (!uniqueCommitEvents.has(key)) uniqueCommitEvents.set(key, event); + } + + return uniqueCommitEvents; +} + +export function getMatchingCommitEvents( + uniqueCommitEvents: Map, + revealEvents: VoteRevealedEvent[] +): VoteCommittedEvent[] { + return revealEvents + .map((event) => uniqueCommitEvents.get(getVoteKey(event))) + .filter((event): event is VoteCommittedEvent => event !== undefined); +} + +export function dedupeTransactionReceipts(transactions: TransactionReceipt[]): TransactionReceipt[] { + return transactions.reduce((accumulator: TransactionReceipt[], current) => { + if (!accumulator.find((transaction) => transaction.transactionHash === current.transactionHash)) + accumulator.push(current); + + return accumulator; + }, []); +} + +function createEventCollectionStats(maxBlockLookBack: number): EventCollectionStats { + return { + maxBlockLookBack, + minBlockLookBack: 1, + rangesQueried: 0, + queryAttempts: 0, + retryCount: 0, + splitCount: 0, + validationFailures: 0, + providerErrors: 0, + receiptValidationCount: 0, + commitEventCount: 0, + revealEventCount: 0, + validationPassed: false, + }; +} + +function getBlockRanges(fromBlock: number, toBlock: number, maxBlockLookBack: number): [number, number][] { + if (fromBlock > toBlock) return []; + if (maxBlockLookBack <= 0) throw new Error("Cannot set maxBlockLookBack <= 0"); + + const ranges: [number, number][] = []; + for (let rangeStart = fromBlock; rangeStart <= toBlock; rangeStart += maxBlockLookBack) { + ranges.push([rangeStart, Math.min(rangeStart + maxBlockLookBack - 1, toBlock)]); + } + return ranges; +} + +function getEventTopic(voting: VotingV2, eventName: "VoteCommitted" | "VoteRevealed"): string { + const contractInterface = (voting as any).interface; + if (contractInterface?.getEventTopic) return contractInterface.getEventTopic(eventName); + + const filter = eventName === "VoteCommitted" ? voting.filters.VoteCommitted() : voting.filters.VoteRevealed(); + const topics = (filter as any).topics; + return Array.isArray(topics) && typeof topics[0] === "string" ? topics[0] : eventName; +} + +function countReceiptEventLogs(receipt: TransactionReceipt, votingAddress: string, topic: string): number { + const votingAddressLower = votingAddress.toLowerCase(); + const topicLower = topic.toLowerCase(); + const logs = receipt.logs || []; + + return logs.filter( + (log) => log.address.toLowerCase() === votingAddressLower && log.topics[0]?.toLowerCase() === topicLower + ).length; +} + +function addProviderFailureStats(stats: EventCollectionStats, _error: unknown, _attempt: number, willRetry: boolean) { + stats.providerErrors++; + if (willRetry) stats.retryCount++; +} + +async function queryEventsForRange( + voting: VotingV2, + filter: ReturnType | ReturnType, + fromBlock: number, + toBlock: number, + stats: EventCollectionStats, + retryConfig?: RetryConfig +): Promise { + const events = await retryAsyncOperation( + async () => { + stats.queryAttempts++; + return ((await voting.queryFilter(filter, fromBlock, toBlock)) as unknown) as T[]; + }, + retryConfig?.retries, + retryConfig?.delay, + (error, attempt, willRetry) => addProviderFailureStats(stats, error, attempt, willRetry) + ); + + return events.filter((event) => event.blockNumber >= fromBlock && event.blockNumber <= toBlock); +} + +async function queryVotingEventsForRange( + voting: VotingV2, + fromBlock: number, + toBlock: number, + stats: EventCollectionStats, + anomalies: RebateAnomaly[], + retryConfig?: RetryConfig +): Promise { + try { + const [commitEvents, revealEvents] = await Promise.all([ + queryEventsForRange( + voting, + voting.filters.VoteCommitted(), + fromBlock, + toBlock, + stats, + retryConfig + ), + queryEventsForRange( + voting, + voting.filters.VoteRevealed(), + fromBlock, + toBlock, + stats, + retryConfig + ), + ]); + + return { + commitEvents: sortEventsByBlockAndLogIndex(commitEvents), + revealEvents: sortEventsByBlockAndLogIndex(revealEvents), + }; + } catch (error) { + anomalies.push({ + type: "provider_error", + message: `Failed to query VotingV2 events for block range ${fromBlock}-${toBlock}: ${error}`, + fromBlock, + toBlock, + }); + stats.validationPassed = false; + throw new EventCollectionValidationError( + `VotingV2 event query failed for block range ${fromBlock}-${toBlock}`, + stats, + anomalies + ); + } +} + +function countCollectedEventsByTransaction( + commitEvents: VoteCommittedEvent[], + revealEvents: VoteRevealedEvent[] +): Map { + const counts = new Map(); + const increment = (transactionHash: string, eventType: keyof TransactionEventCounts) => { + const current = counts.get(transactionHash) || { commit: 0, reveal: 0 }; + current[eventType]++; + counts.set(transactionHash, current); + }; + + for (const event of commitEvents) increment(event.transactionHash, "commit"); + for (const event of revealEvents) increment(event.transactionHash, "reveal"); + + return counts; +} + +async function validateCollectedRange( + voting: VotingV2, + fromBlock: number, + toBlock: number, + commitEvents: VoteCommittedEvent[], + revealEvents: VoteRevealedEvent[], + receiptByTransactionHash: Map, + transactionConcurrency: number, + stats: EventCollectionStats, + anomalies: RebateAnomaly[], + retryConfig?: RetryConfig +): Promise { + const collectedCounts = countCollectedEventsByTransaction(commitEvents, revealEvents); + const transactionHashes = [...collectedCounts.keys()].sort(); + if (transactionHashes.length === 0) return true; + + const voteCommittedTopic = getEventTopic(voting, "VoteCommitted"); + const voteRevealedTopic = getEventTopic(voting, "VoteRevealed"); + const validationAnomalies: RebateAnomaly[] = []; + + try { + await Bluebird.map( + transactionHashes, + async (transactionHash) => { + const receipt = await retryAsyncOperation( + async () => await voting.provider.getTransactionReceipt(transactionHash), + retryConfig?.retries, + retryConfig?.delay, + (error, attempt, willRetry) => addProviderFailureStats(stats, error, attempt, willRetry) + ); + + stats.receiptValidationCount++; + if (!receipt) { + validationAnomalies.push({ + type: "missing_receipt", + message: `Missing transaction receipt for discovered VotingV2 event transaction ${transactionHash}`, + fromBlock, + toBlock, + transactionHash, + }); + return; + } + + receiptByTransactionHash.set(transactionHash, receipt); + const collected = collectedCounts.get(transactionHash) as TransactionEventCounts; + const receiptCommitCount = countReceiptEventLogs(receipt, voting.address, voteCommittedTopic); + const receiptRevealCount = countReceiptEventLogs(receipt, voting.address, voteRevealedTopic); + + if (receiptCommitCount !== collected.commit || receiptRevealCount !== collected.reveal) { + validationAnomalies.push({ + type: "receipt_event_count_mismatch", + message: + `Receipt log count mismatch for ${transactionHash}: ` + + `collected ${collected.commit} commits/${collected.reveal} reveals, ` + + `receipt has ${receiptCommitCount} commits/${receiptRevealCount} reveals`, + fromBlock, + toBlock, + transactionHash, + details: { + collectedCommitCount: collected.commit, + collectedRevealCount: collected.reveal, + receiptCommitCount, + receiptRevealCount, + }, + }); + } + }, + { concurrency: transactionConcurrency } + ); + } catch (error) { + anomalies.push({ + type: "provider_error", + message: `Failed to validate VotingV2 event receipt logs for block range ${fromBlock}-${toBlock}: ${error}`, + fromBlock, + toBlock, + }); + stats.validationPassed = false; + throw new EventCollectionValidationError( + `VotingV2 event receipt validation failed for block range ${fromBlock}-${toBlock}`, + stats, + anomalies + ); + } + + anomalies.push(...validationAnomalies); + return validationAnomalies.length === 0; +} + +async function collectRangeWithValidation( + voting: VotingV2, + fromBlock: number, + toBlock: number, + transactionConcurrency: number, + stats: EventCollectionStats, + anomalies: RebateAnomaly[], + receiptByTransactionHash: Map, + retryConfig?: RetryConfig +): Promise { + stats.rangesQueried++; + + const rangeEvents = await queryVotingEventsForRange(voting, fromBlock, toBlock, stats, anomalies, retryConfig); + const isValid = await validateCollectedRange( + voting, + fromBlock, + toBlock, + rangeEvents.commitEvents, + rangeEvents.revealEvents, + receiptByTransactionHash, + transactionConcurrency, + stats, + anomalies, + retryConfig + ); + + if (isValid) return rangeEvents; + + stats.validationFailures++; + if (fromBlock >= toBlock) { + stats.validationPassed = false; + throw new EventCollectionValidationError( + `VotingV2 event collection validation failed at minimum block range ${fromBlock}-${toBlock}`, + stats, + anomalies + ); + } + + stats.splitCount++; + const midBlock = Math.floor((fromBlock + toBlock) / 2); + const leftEvents = await collectRangeWithValidation( + voting, + fromBlock, + midBlock, + transactionConcurrency, + stats, + anomalies, + receiptByTransactionHash, + retryConfig + ); + const rightEvents = await collectRangeWithValidation( + voting, + midBlock + 1, + toBlock, + transactionConcurrency, + stats, + anomalies, + receiptByTransactionHash, + retryConfig + ); + + return { + commitEvents: [...leftEvents.commitEvents, ...rightEvents.commitEvents], + revealEvents: [...leftEvents.revealEvents, ...rightEvents.revealEvents], + }; +} + +export async function collectVotingV2Events({ + voting, + fromBlock, + toBlock, + maxBlockLookBack, + transactionConcurrency, + retryConfig, +}: Pick< + CalculateVoterGasRebateV2Config, + "voting" | "fromBlock" | "toBlock" | "maxBlockLookBack" | "transactionConcurrency" | "retryConfig" +>): Promise { + const stats = createEventCollectionStats(maxBlockLookBack); + const anomalies: RebateAnomaly[] = []; + const receiptByTransactionHash = new Map(); + const rangeResults: CollectedRangeEvents[] = []; + + for (const [rangeFromBlock, rangeToBlock] of getBlockRanges(fromBlock, toBlock, maxBlockLookBack)) { + rangeResults.push( + await collectRangeWithValidation( + voting, + rangeFromBlock, + rangeToBlock, + transactionConcurrency, + stats, + anomalies, + receiptByTransactionHash, + retryConfig + ) + ); + } + + const commitEvents = sortEventsByBlockAndLogIndex(rangeResults.flatMap((result) => result.commitEvents)); + const revealEvents = sortEventsByBlockAndLogIndex(rangeResults.flatMap((result) => result.revealEvents)); + + stats.commitEventCount = commitEvents.length; + stats.revealEventCount = revealEvents.length; + stats.validationPassed = true; + + return { + commitEvents, + revealEvents, + receiptByTransactionHash, + eventCollectionStats: stats, + anomalies, + }; +} + +async function getTransactionsFromEvents( + voting: VotingV2, + events: Event[], + transactionConcurrency: number, + retryConfig?: RetryConfig, + receiptByTransactionHash?: Map +): Promise { + return await Bluebird.map( + events, + async (event) => { + const cachedReceipt = receiptByTransactionHash?.get(event.transactionHash); + if (cachedReceipt) return cachedReceipt; + + return await retryAsyncOperation( + async () => await voting.provider.getTransactionReceipt(event.transactionHash), + retryConfig?.retries, + retryConfig?.delay + ); + }, + { concurrency: transactionConcurrency } + ); +} + +export async function calculateVoterGasRebateV2({ + voting, + fromBlock, + toBlock, + minTokens, + maxBlockLookBack, + transactionConcurrency, + maxPriorityFee, + retryConfig, +}: CalculateVoterGasRebateV2Config): Promise { + const eventCollection = await collectVotingV2Events({ + voting, + fromBlock, + toBlock, + maxBlockLookBack, + transactionConcurrency, + retryConfig, + }); + const { commitEvents, revealEvents, receiptByTransactionHash, eventCollectionStats } = eventCollection; + const anomalies = [...eventCollection.anomalies]; + + const eligibleRevealEvents = revealEvents.filter((event) => event.args.numTokens.gte(minTokens)); + const uniqueCommitEvents = getUniqueCommitEvents(commitEvents); + const matchingCommitEvents = getMatchingCommitEvents(uniqueCommitEvents, eligibleRevealEvents); + const missingCommitRevealEvents = eligibleRevealEvents.filter((event) => !uniqueCommitEvents.has(getVoteKey(event))); + + anomalies.push( + ...missingCommitRevealEvents.map((event) => ({ + type: "reveal_missing_commit" as const, + message: `Eligible reveal ${event.transactionHash} has no matching commit event in the collected block range`, + fromBlock, + toBlock, + transactionHash: event.transactionHash, + voter: event.args.voter, + })) + ); + + const commitTransactions = await getTransactionsFromEvents( + voting, + matchingCommitEvents, + transactionConcurrency, + retryConfig, + receiptByTransactionHash + ); + const revealTransactions = await getTransactionsFromEvents( + voting, + eligibleRevealEvents, + transactionConcurrency, + retryConfig, + receiptByTransactionHash + ); + + const transactionsToRefund = dedupeTransactionReceipts([...commitTransactions, ...revealTransactions]); + const uniqueBlockNumbers = [...new Set(transactionsToRefund.map((tx) => tx.blockNumber))]; + const blockDataMap = new Map(); + + await Bluebird.map( + uniqueBlockNumbers, + async (blockNumber) => { + const block = await retryAsyncOperation( + async () => await voting.provider.getBlock(blockNumber), + retryConfig?.retries, + retryConfig?.delay + ); + if (block.baseFeePerGas) blockDataMap.set(blockNumber, block.baseFeePerGas); + }, + { concurrency: transactionConcurrency } + ); + + const shareholderPayoutWei: { [address: string]: BigNumber } = {}; + const transactionEvidence: RebateTransactionEvidence[] = []; + + for (const transaction of transactionsToRefund) { + const baseFee = blockDataMap.get(transaction.blockNumber); + let effectiveGasPriceForRebate: BigNumber; + let actualPriorityFee: BigNumber | null = null; + let cappedPriorityFee: BigNumber | null = null; + + if (baseFee) { + actualPriorityFee = transaction.effectiveGasPrice.sub(baseFee); + cappedPriorityFee = maxPriorityFee && actualPriorityFee.gt(maxPriorityFee) ? maxPriorityFee : actualPriorityFee; + effectiveGasPriceForRebate = baseFee.add(cappedPriorityFee); + } else { + effectiveGasPriceForRebate = transaction.effectiveGasPrice; + } + + const resultantRebate = transaction.gasUsed.mul(effectiveGasPriceForRebate); + if (!shareholderPayoutWei[transaction.from]) shareholderPayoutWei[transaction.from] = BigNumber.from(0); + shareholderPayoutWei[transaction.from] = shareholderPayoutWei[transaction.from].add(resultantRebate); + + transactionEvidence.push({ + transactionHash: transaction.transactionHash, + from: transaction.from, + blockNumber: transaction.blockNumber, + gasUsed: transaction.gasUsed.toString(), + effectiveGasPrice: transaction.effectiveGasPrice.toString(), + baseFee: baseFee ? baseFee.toString() : null, + actualPriorityFee: actualPriorityFee ? actualPriorityFee.toString() : null, + cappedPriorityFee: cappedPriorityFee ? cappedPriorityFee.toString() : null, + effectiveGasPriceForRebate: effectiveGasPriceForRebate.toString(), + rebateWei: resultantRebate.toString(), + }); + } + + const totalRebateWei = Object.values(shareholderPayoutWei).reduce((a, b) => a.add(b), BigNumber.from(0)); + + return { + votingContractAddress: voting.address, + fromBlock, + toBlock, + minStakedTokens: minTokens, + maxBlockLookBack, + transactionConcurrency, + maxPriorityFee, + commitEvents, + revealEvents, + eligibleRevealEvents, + matchingCommitEvents, + transactionsToRefund, + shareholderPayoutWei, + totalRebateWei, + transactionEvidence, + eventCollectionStats, + anomalies, + }; +} + +function assertPlainObject(value: unknown, name: string): asserts value is { [key: string]: unknown } { + if (typeof value !== "object" || value === null || Array.isArray(value)) { + throw new CorrectionManifestValidationError(`${name} must be an object`); + } +} + +function assertNonEmptyString(value: unknown, name: string): string { + if (typeof value !== "string" || value.trim() === "") { + throw new CorrectionManifestValidationError(`${name} must be a non-empty string`); + } + return value; +} + +function assertSafeInteger(value: unknown, name: string, minimum?: number): number { + if (typeof value !== "number" || !Number.isSafeInteger(value) || (minimum !== undefined && value < minimum)) { + throw new CorrectionManifestValidationError(`${name} must be a safe integer`); + } + return value; +} + +function normalizeAddress(value: unknown, name: string): string { + const address = assertNonEmptyString(value, name); + try { + return utils.getAddress(address); + } catch (error) { + throw new CorrectionManifestValidationError(`${name} must be a valid Ethereum address`); + } +} + +function validateBlockRange(fromBlock: number, toBlock: number, name: string) { + if (fromBlock > toBlock) { + throw new CorrectionManifestValidationError( + `${name} has invalid block range: fromBlock (${fromBlock}) > toBlock (${toBlock})` + ); + } +} + +function resolveInputPath(filePath: string, baseDir: string): string { + return path.isAbsolute(filePath) ? filePath : path.resolve(baseDir, filePath); +} + +function expandScientificNotation(value: string): string { + if (!/[eE]/.test(value)) return value; + + const [coefficient, exponentValue] = value.toLowerCase().split("e"); + const exponent = Number(exponentValue); + if (!Number.isSafeInteger(exponent)) throw new Error(`Invalid decimal exponent: ${value}`); + + const [integerPart, fractionalPart = ""] = coefficient.split("."); + const digits = `${integerPart}${fractionalPart}`.replace(/^0+(?=\d)/, ""); + const decimalIndex = integerPart.length + exponent; + + if (decimalIndex <= 0) return `0.${"0".repeat(Math.abs(decimalIndex))}${digits}`; + if (decimalIndex >= digits.length) return `${digits}${"0".repeat(decimalIndex - digits.length)}`; + return `${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`; +} + +export function parseEthDecimalToWei(value: number | string): BigNumber { + if (typeof value !== "number" && typeof value !== "string") { + throw new CorrectionManifestValidationError("ETH amount must be a number or decimal string"); + } + + if (typeof value === "number" && (!Number.isFinite(value) || value < 0)) { + throw new CorrectionManifestValidationError("ETH amount number must be finite and non-negative"); + } + + const rawDecimal = typeof value === "number" ? expandScientificNotation(value.toString()) : value.trim(); + if (rawDecimal.startsWith("-")) { + throw new CorrectionManifestValidationError("ETH amount must be non-negative"); + } + if (!/^\d+(\.\d+)?$/.test(rawDecimal)) { + throw new CorrectionManifestValidationError(`ETH amount must be a decimal value: ${value}`); + } + + const [integerPart, fractionalPart = ""] = rawDecimal.split("."); + const extraFractionalDigits = fractionalPart.slice(18); + if (extraFractionalDigits.length > 0 && /[1-9]/.test(extraFractionalDigits)) { + throw new CorrectionManifestValidationError(`ETH amount has more than 18 decimal places: ${value}`); + } + + const weiString = `${integerPart}${fractionalPart.padEnd(18, "0").slice(0, 18)}`.replace(/^0+(?=\d)/, ""); + return BigNumber.from(weiString || "0"); +} + +export function formatWeiToEthDecimalString(value: BigNumber): string { + return utils.formatEther(value); +} + +function parseWeiString(value: unknown, name: string): BigNumber { + const rawValue = assertNonEmptyString(value, name); + if (!/^-?\d+$/.test(rawValue)) { + throw new CorrectionManifestValidationError(`${name} must be an integer wei string`); + } + return BigNumber.from(rawValue); +} + +function validateDecimalString(value: unknown, name: string): string { + const decimal = assertNonEmptyString(value, name); + parseEthDecimalToWei(decimal); + return decimal; +} + +function validateGweiDecimalString(value: unknown, name: string): string | null { + if (value === null) return null; + const decimal = assertNonEmptyString(value, name); + try { + utils.parseUnits(decimal, "gwei"); + } catch (error) { + throw new CorrectionManifestValidationError(`${name} must be a decimal gwei value`); + } + return decimal; +} + +function normalizePayoutWei(shareholderPayout: { + [address: string]: number | string; +}): { [address: string]: BigNumber } { + return Object.entries(shareholderPayout).reduce((payoutWei: { [address: string]: BigNumber }, [address, amount]) => { + const normalizedAddress = normalizeAddress(address, "shareholderPayout address"); + const amountWei = parseEthDecimalToWei(amount); + payoutWei[normalizedAddress] = (payoutWei[normalizedAddress] || BigNumber.from(0)).add(amountWei); + return payoutWei; + }, {}); +} + +function normalizeRecomputedPayoutWei(shareholderPayoutWei: { + [address: string]: BigNumber; +}): { + [address: string]: BigNumber; +} { + return Object.entries(shareholderPayoutWei).reduce( + (payoutWei: { [address: string]: BigNumber }, [address, amount]) => { + const normalizedAddress = normalizeAddress(address, "recomputed shareholder address"); + payoutWei[normalizedAddress] = (payoutWei[normalizedAddress] || BigNumber.from(0)).add(amount); + return payoutWei; + }, + {} + ); +} + +function totalWei(payoutWei: { [address: string]: BigNumber }): BigNumber { + return Object.values(payoutWei).reduce((total, amount) => total.add(amount), BigNumber.from(0)); +} + +function loadJsonFile(filePath: string, label: string): unknown { + if (!fs.existsSync(filePath)) { + throw new CorrectionManifestValidationError(`${label} not found: ${filePath}`); + } + + try { + return JSON.parse(fs.readFileSync(filePath, "utf8")); + } catch (error) { + throw new CorrectionManifestValidationError(`${label} is malformed JSON: ${filePath}`); + } +} + +function validatePaidRebateFile( + rebateFile: unknown, + rebateFilePath: string, + entry: CorrectionManifestAuditEntry, + expectedVotingContractAddress: string +): PaidRebateFile { + assertPlainObject(rebateFile, `Paid rebate file ${rebateFilePath}`); + + const paidVotingContractAddress = normalizeAddress( + rebateFile.votingContractAddress, + `Paid rebate file ${rebateFilePath} votingContractAddress` + ); + if (paidVotingContractAddress.toLowerCase() !== expectedVotingContractAddress.toLowerCase()) { + throw new CorrectionManifestValidationError( + `Paid rebate file ${rebateFilePath} uses non-VotingV2 contract ${paidVotingContractAddress}` + ); + } + + const rebate = assertSafeInteger(rebateFile.rebate, `Paid rebate file ${rebateFilePath} rebate`, 0); + const fromBlock = assertSafeInteger(rebateFile.fromBlock, `Paid rebate file ${rebateFilePath} fromBlock`, 0); + const toBlock = assertSafeInteger(rebateFile.toBlock, `Paid rebate file ${rebateFilePath} toBlock`, 0); + const countVoters = assertSafeInteger(rebateFile.countVoters, `Paid rebate file ${rebateFilePath} countVoters`, 0); + validateBlockRange(fromBlock, toBlock, `Paid rebate file ${rebateFilePath}`); + + if (rebate !== entry.rebateNumber) { + throw new CorrectionManifestValidationError( + `Manifest rebateNumber ${entry.rebateNumber} does not match paid rebate file ${rebateFilePath} rebate ${rebate}` + ); + } + if (fromBlock !== entry.fromBlock || toBlock !== entry.toBlock) { + throw new CorrectionManifestValidationError( + `Manifest block range ${entry.fromBlock}-${entry.toBlock} does not match paid rebate file ${rebateFilePath} ` + + `range ${fromBlock}-${toBlock}` + ); + } + + if (typeof rebateFile.totalRebateAmount !== "number" && typeof rebateFile.totalRebateAmount !== "string") { + throw new CorrectionManifestValidationError(`Paid rebate file ${rebateFilePath} totalRebateAmount is invalid`); + } + parseEthDecimalToWei(rebateFile.totalRebateAmount); + + assertPlainObject(rebateFile.shareholderPayout, `Paid rebate file ${rebateFilePath} shareholderPayout`); + normalizePayoutWei(rebateFile.shareholderPayout as { [address: string]: number | string }); + + return { + votingContractAddress: paidVotingContractAddress, + rebate, + fromBlock, + toBlock, + countVoters, + totalRebateAmount: rebateFile.totalRebateAmount as number | string, + shareholderPayout: rebateFile.shareholderPayout as { [address: string]: number | string }, + }; +} + +function validateOutputPrefix(value: unknown): string { + const outputPrefix = assertNonEmptyString(value, "manifest outputPrefix"); + if (!/^[A-Za-z0-9_.-]+$/.test(outputPrefix)) { + throw new CorrectionManifestValidationError( + "manifest outputPrefix may only contain letters, numbers, periods, underscores, and hyphens" + ); + } + return outputPrefix; +} + +function validateCorrectionManifestAuditEntry( + value: unknown, + index: number, + baseDir: string, + votingContractAddress: string +): ValidatedCorrectionManifestAuditEntry { + assertPlainObject(value, `manifest audits[${index}]`); + + const rebateFile = assertNonEmptyString(value.rebateFile, `manifest audits[${index}].rebateFile`); + const rebateNumber = assertSafeInteger(value.rebateNumber, `manifest audits[${index}].rebateNumber`, 0); + const fromBlock = assertSafeInteger(value.fromBlock, `manifest audits[${index}].fromBlock`, 0); + const toBlock = assertSafeInteger(value.toBlock, `manifest audits[${index}].toBlock`, 0); + validateBlockRange(fromBlock, toBlock, `manifest audits[${index}]`); + + const minStakedTokens = validateDecimalString(value.minStakedTokens, `manifest audits[${index}].minStakedTokens`); + const maxPriorityFeeGwei = validateGweiDecimalString( + value.maxPriorityFeeGwei, + `manifest audits[${index}].maxPriorityFeeGwei` + ); + const maxBlockLookBack = assertSafeInteger(value.maxBlockLookBack, `manifest audits[${index}].maxBlockLookBack`, 1); + const transactionConcurrency = assertSafeInteger( + value.transactionConcurrency, + `manifest audits[${index}].transactionConcurrency`, + 1 + ); + const notes = + value.notes === undefined ? undefined : assertNonEmptyString(value.notes, `manifest audits[${index}].notes`); + const paidRebateFilePath = resolveInputPath(rebateFile, baseDir); + + const entry = { + rebateFile, + rebateNumber, + fromBlock, + toBlock, + minStakedTokens, + maxPriorityFeeGwei, + maxBlockLookBack, + transactionConcurrency, + ...(notes ? { notes } : {}), + }; + const paidRebate = validatePaidRebateFile( + loadJsonFile(paidRebateFilePath, `Paid rebate file ${paidRebateFilePath}`), + paidRebateFilePath, + entry, + votingContractAddress + ); + + return { + ...entry, + paidRebateFilePath, + paidRebate, + minStakedTokensWei: parseEthDecimalToWei(minStakedTokens).toString(), + maxPriorityFeeWei: maxPriorityFeeGwei === null ? null : utils.parseUnits(maxPriorityFeeGwei, "gwei").toString(), + }; +} + +function validateExpectedDeltas(value: unknown): CorrectionExpectedDelta[] { + if (!Array.isArray(value)) { + throw new CorrectionManifestValidationError("manifest expectedDeltas must be an array"); + } + + const seenExpectedDeltas = new Set(); + return value.map((delta, index) => { + assertPlainObject(delta, `manifest expectedDeltas[${index}]`); + const rebateNumber = assertSafeInteger(delta.rebateNumber, `manifest expectedDeltas[${index}].rebateNumber`, 0); + const address = normalizeAddress(delta.address, `manifest expectedDeltas[${index}].address`); + const deltaWei = parseWeiString(delta.deltaWei, `manifest expectedDeltas[${index}].deltaWei`).toString(); + const expectedDeltaKey = `${rebateNumber}:${address.toLowerCase()}`; + + if (seenExpectedDeltas.has(expectedDeltaKey)) { + throw new CorrectionManifestValidationError( + `Duplicate expected delta for rebate ${rebateNumber} address ${address}` + ); + } + seenExpectedDeltas.add(expectedDeltaKey); + + return { + rebateNumber, + address, + deltaWei, + }; + }); +} + +function validateNoOverlappingAuditRanges(audits: ValidatedCorrectionManifestAuditEntry[]) { + const sortedAudits = [...audits].sort((a, b) => { + if (a.fromBlock !== b.fromBlock) return a.fromBlock - b.fromBlock; + return a.toBlock - b.toBlock; + }); + + for (let index = 1; index < sortedAudits.length; index++) { + const previous = sortedAudits[index - 1]; + const current = sortedAudits[index]; + if (current.fromBlock <= previous.toBlock) { + throw new CorrectionManifestValidationError( + `Manifest audit block ranges overlap: rebate ${previous.rebateNumber} ` + + `${previous.fromBlock}-${previous.toBlock} and rebate ${current.rebateNumber} ` + + `${current.fromBlock}-${current.toBlock}` + ); + } + } +} + +function validateExpectedDeltasReferenceAudits( + expectedDeltas: CorrectionExpectedDelta[], + audits: ValidatedCorrectionManifestAuditEntry[] +) { + const auditedRebateNumbers = new Set(audits.map((audit) => audit.rebateNumber)); + for (const expectedDelta of expectedDeltas) { + if (!auditedRebateNumbers.has(expectedDelta.rebateNumber)) { + throw new CorrectionManifestValidationError( + `Expected delta references rebate ${expectedDelta.rebateNumber}, which is not in manifest audits` + ); + } + } +} + +export function loadCorrectionManifest( + manifestPath: string, + options: { baseDir?: string; expectedVotingContractAddress?: string } = {} +): ValidatedCorrectionManifest { + const absoluteManifestPath = path.resolve(manifestPath); + const baseDir = options.baseDir ? path.resolve(options.baseDir) : process.cwd(); + const manifest = loadJsonFile(absoluteManifestPath, `Correction manifest ${absoluteManifestPath}`); + assertPlainObject(manifest, "Correction manifest"); + + if (manifest.version !== 1) { + throw new CorrectionManifestValidationError("manifest version must be 1"); + } + + const name = assertNonEmptyString(manifest.name, "manifest name"); + const votingContractAddress = normalizeAddress(manifest.votingContractAddress, "manifest votingContractAddress"); + const expectedVotingContractAddress = options.expectedVotingContractAddress + ? normalizeAddress(options.expectedVotingContractAddress, "expected VotingV2 contract address") + : votingContractAddress; + + if (votingContractAddress.toLowerCase() !== expectedVotingContractAddress.toLowerCase()) { + throw new CorrectionManifestValidationError( + `Manifest uses non-VotingV2 contract ${votingContractAddress}; expected ${expectedVotingContractAddress}` + ); + } + + const outputPrefix = validateOutputPrefix(manifest.outputPrefix); + if (!Array.isArray(manifest.audits) || manifest.audits.length === 0) { + throw new CorrectionManifestValidationError("manifest audits must be a non-empty array"); + } + + const audits = manifest.audits.map((audit, index) => + validateCorrectionManifestAuditEntry(audit, index, baseDir, votingContractAddress) + ); + validateNoOverlappingAuditRanges(audits); + + const expectedDeltas = validateExpectedDeltas(manifest.expectedDeltas); + validateExpectedDeltasReferenceAudits(expectedDeltas, audits); + + return { + version: 1, + name, + votingContractAddress, + outputPrefix, + audits, + expectedDeltas, + }; +} + +export function diffPaidVersusRecomputedAmounts( + paidPayoutWei: { [address: string]: BigNumber }, + recomputedPayoutWei: { [address: string]: BigNumber } +): CorrectionAddressDelta[] { + const addresses = [...new Set([...Object.keys(paidPayoutWei), ...Object.keys(recomputedPayoutWei)])].sort((a, b) => + a.toLowerCase().localeCompare(b.toLowerCase()) + ); + + return addresses.map((address) => { + const paidWei = paidPayoutWei[address] || BigNumber.from(0); + const recomputedWei = recomputedPayoutWei[address] || BigNumber.from(0); + return { + address, + paidWei: paidWei.toString(), + recomputedWei: recomputedWei.toString(), + deltaWei: recomputedWei.sub(paidWei).toString(), + }; + }); +} + +function splitCorrectionDeltas( + deltas: CorrectionAddressDelta[] +): { + positive: CorrectionAddressDelta[]; + zero: CorrectionAddressDelta[]; + negative: CorrectionAddressDelta[]; +} { + return { + positive: deltas.filter((delta) => BigNumber.from(delta.deltaWei).gt(0)), + zero: deltas.filter((delta) => BigNumber.from(delta.deltaWei).eq(0)), + negative: deltas.filter((delta) => BigNumber.from(delta.deltaWei).lt(0)), + }; +} + +function sumDeltaWei(deltas: CorrectionAddressDelta[]): BigNumber { + return deltas.reduce((total, delta) => total.add(BigNumber.from(delta.deltaWei)), BigNumber.from(0)); +} + +export function getCorrectionArtifactPaths(outputDir: string, outputPrefix: string): CorrectionArtifactPaths { + return { + payoutPath: path.join(outputDir, `${outputPrefix}.json`), + auditJsonPath: path.join(outputDir, `${outputPrefix}.audit.json`), + auditMarkdownPath: path.join(outputDir, `${outputPrefix}.audit.md`), + }; +} + +function assertCanWriteCorrectionArtifacts(paths: CorrectionArtifactPaths, allowOverwrite: boolean) { + const existingOutputPaths = [paths.payoutPath, paths.auditJsonPath, paths.auditMarkdownPath].filter((outputPath) => + fs.existsSync(outputPath) + ); + if (!allowOverwrite && existingOutputPaths.length > 0) { + throw new Error( + `Refusing to overwrite existing correction output(s): ${existingOutputPaths.join(", ")}. ` + + "Set ALLOW_OVERWRITE=true to replace them." + ); + } +} + +function buildCorrectionPayoutJson( + manifest: ValidatedCorrectionManifest, + consolidatedPayoutWei: { [address: string]: BigNumber } +): CorrectionPayoutJson { + const sortedAddresses = Object.keys(consolidatedPayoutWei).sort((a, b) => + a.toLowerCase().localeCompare(b.toLowerCase()) + ); + const shareholderPayout = sortedAddresses.reduce((payout: { [address: string]: number }, address) => { + payout[address] = parseFloat(formatWeiToEthDecimalString(consolidatedPayoutWei[address])); + return payout; + }, {}); + const totalRebateWei = totalWei(consolidatedPayoutWei); + const fromBlock = Math.min(...manifest.audits.map((audit) => audit.fromBlock)); + const toBlock = Math.max(...manifest.audits.map((audit) => audit.toBlock)); + const rebate = Math.min(...manifest.audits.map((audit) => audit.rebateNumber)); + + return { + votingContractAddress: manifest.votingContractAddress, + rebate, + fromBlock, + toBlock, + countVoters: sortedAddresses.length, + totalRebateAmount: parseFloat(formatWeiToEthDecimalString(totalRebateWei)), + shareholderPayout, + }; +} + +function getPositiveDeltaEvidence( + result: RebateComputationResult, + positiveDeltas: CorrectionAddressDelta[] +): RebateTransactionEvidence[] { + const positiveAddresses = new Set(positiveDeltas.map((delta) => delta.address.toLowerCase())); + return result.transactionEvidence.filter((evidence) => positiveAddresses.has(evidence.from.toLowerCase())); +} + +function buildExpectedDeltaChecks( + manifest: ValidatedCorrectionManifest, + deltaByRebateAndAddress: Map +): CorrectionExpectedDeltaCheck[] { + return manifest.expectedDeltas.map((expectedDelta) => { + const key = `${expectedDelta.rebateNumber}:${expectedDelta.address.toLowerCase()}`; + const actualDelta = deltaByRebateAndAddress.get(key); + const actualDeltaWei = actualDelta ? actualDelta.deltaWei : "0"; + return { + rebateNumber: expectedDelta.rebateNumber, + address: expectedDelta.address, + expectedDeltaWei: expectedDelta.deltaWei, + actualDeltaWei, + passed: BigNumber.from(actualDeltaWei).eq(BigNumber.from(expectedDelta.deltaWei)), + }; + }); +} + +function validateExpectedDeltaChecks(expectedDeltaChecks: CorrectionExpectedDeltaCheck[]) { + const failedChecks = expectedDeltaChecks.filter((check) => !check.passed); + if (failedChecks.length > 0) { + throw new Error( + "Expected delta mismatch: " + + failedChecks + .map( + (check) => + `rebate ${check.rebateNumber} ${check.address} expected ${check.expectedDeltaWei} actual ${check.actualDeltaWei}` + ) + .join("; ") + ); + } +} + +function getManifestHash(manifestPath: string): string { + return createHash("sha256").update(fs.readFileSync(manifestPath)).digest("hex"); +} + +function formatCorrectionAuditMarkdown(report: CorrectionAuditReport): string { + const auditedRebateLines = report.auditedRebates.flatMap((rebateReport) => [ + `### Rebate ${rebateReport.rebateNumber}`, + "", + `- Paid file: \`${rebateReport.rebateFile}\``, + ...(rebateReport.notes ? [`- Notes: ${rebateReport.notes}`] : []), + `- Block range: ${rebateReport.blockRange.fromBlock}-${rebateReport.blockRange.toBlock}`, + `- Paid total: ${rebateReport.paid.totalRebateWei} wei (${rebateReport.paid.totalRebateEth} ETH)`, + `- Recomputed total: ${rebateReport.recomputed.totalRebateWei} wei (${rebateReport.recomputed.totalRebateEth} ETH)`, + `- Positive delta total: ${rebateReport.deltas.positiveTotalWei} wei (${rebateReport.deltas.positiveTotalEth} ETH)`, + `- Negative delta total: ${rebateReport.deltas.negativeTotalWei} wei (${rebateReport.deltas.negativeTotalEth} ETH)`, + `- Positive delta count: ${rebateReport.deltas.positive.length}`, + `- Negative delta count: ${rebateReport.deltas.negative.length}`, + `- Event validation passed: ${rebateReport.eventCollection.validationPassed}`, + `- Retry count: ${rebateReport.eventCollection.retryCount}`, + `- Split count: ${rebateReport.eventCollection.splitCount}`, + `- Anomalies: ${rebateReport.anomalies.length}`, + "", + ]); + const expectedDeltaLines = + report.expectedDeltaChecks.length === 0 + ? ["- None"] + : report.expectedDeltaChecks.map( + (check) => + `- Rebate ${check.rebateNumber} ${check.address}: expected ${check.expectedDeltaWei}, actual ` + + `${check.actualDeltaWei}, passed ${check.passed}` + ); + const negativeDeltaLines = report.auditedRebates.flatMap((rebateReport) => + rebateReport.deltas.negative.map( + (delta) => `- Rebate ${rebateReport.rebateNumber} ${delta.address}: ${delta.deltaWei} wei` + ) + ); + + return [ + `# VotingV2 Gas Rebate Correction Audit - ${report.manifestName}`, + "", + `Generated at: ${report.generatedAt}`, + `Manifest: \`${report.manifestPath}\``, + `Manifest SHA-256: \`${report.manifestHash}\``, + `VotingV2 contract: \`${report.votingContractAddress}\``, + `Custom node URL configured: ${report.customNodeUrlConfigured}`, + "", + "## Consolidated Top-Up", + "", + `- Voters: ${report.consolidatedTopUp.countVoters}`, + `- Total: ${report.consolidatedTopUp.totalWei} wei (${report.consolidatedTopUp.totalEth} ETH)`, + `- Payout JSON: \`${report.outputPaths.payoutPath}\``, + "", + "## Audited Rebates", + "", + ...auditedRebateLines, + "## Expected Delta Checks", + "", + ...expectedDeltaLines, + "", + "## Negative Deltas", + "", + ...(negativeDeltaLines.length === 0 ? ["- None"] : negativeDeltaLines), + "", + ].join("\n"); +} + +export async function runVotingV2CorrectionAudit({ + manifestPath, + voting, + outputDir, + expectedVotingContractAddress, + baseDir, + allowOverwrite = false, + customNodeUrlConfigured = false, + retryConfig, + generatedAt, + calculateRebate = calculateVoterGasRebateV2, +}: RunVotingV2CorrectionAuditOptions): Promise { + const absoluteManifestPath = path.resolve(manifestPath); + const manifest = loadCorrectionManifest(absoluteManifestPath, { + baseDir, + expectedVotingContractAddress, + }); + const paths = getCorrectionArtifactPaths(path.resolve(outputDir), manifest.outputPrefix); + assertCanWriteCorrectionArtifacts(paths, allowOverwrite); + + const deltaByRebateAndAddress = new Map(); + const consolidatedPayoutWei: { [address: string]: BigNumber } = {}; + const auditedRebates: CorrectionAuditRebateReport[] = []; + + for (const entry of manifest.audits) { + const minTokens = BigNumber.from(entry.minStakedTokensWei); + const maxPriorityFee = entry.maxPriorityFeeWei === null ? null : BigNumber.from(entry.maxPriorityFeeWei); + const result = await calculateRebate( + { + voting, + fromBlock: entry.fromBlock, + toBlock: entry.toBlock, + minTokens, + maxBlockLookBack: entry.maxBlockLookBack, + transactionConcurrency: entry.transactionConcurrency, + maxPriorityFee, + retryConfig, + }, + entry, + manifest + ); + + if (result.votingContractAddress.toLowerCase() !== manifest.votingContractAddress.toLowerCase()) { + throw new Error( + `Recomputed rebate ${entry.rebateNumber} used unexpected voting contract ${result.votingContractAddress}` + ); + } + if (result.fromBlock !== entry.fromBlock || result.toBlock !== entry.toBlock) { + throw new Error(`Recomputed rebate ${entry.rebateNumber} returned an unexpected block range`); + } + + const paidPayoutWei = normalizePayoutWei(entry.paidRebate.shareholderPayout); + const recomputedPayoutWei = normalizeRecomputedPayoutWei(result.shareholderPayoutWei); + const paidTotalWei = totalWei(paidPayoutWei); + const recomputedTotalWei = totalWei(recomputedPayoutWei); + const allDeltas = diffPaidVersusRecomputedAmounts(paidPayoutWei, recomputedPayoutWei); + const { positive, zero, negative } = splitCorrectionDeltas(allDeltas); + const positiveTotalWei = sumDeltaWei(positive); + const negativeTotalWei = sumDeltaWei(negative); + + for (const delta of allDeltas) { + deltaByRebateAndAddress.set(`${entry.rebateNumber}:${delta.address.toLowerCase()}`, delta); + } + for (const delta of positive) { + const deltaWei = BigNumber.from(delta.deltaWei); + consolidatedPayoutWei[delta.address] = (consolidatedPayoutWei[delta.address] || BigNumber.from(0)).add(deltaWei); + } + + auditedRebates.push({ + rebateNumber: entry.rebateNumber, + rebateFile: entry.rebateFile, + paidRebateFilePath: entry.paidRebateFilePath, + ...(entry.notes ? { notes: entry.notes } : {}), + blockRange: { + fromBlock: entry.fromBlock, + toBlock: entry.toBlock, + }, + effectiveConfig: { + minStakedTokens: entry.minStakedTokens, + minStakedTokensWei: entry.minStakedTokensWei, + maxPriorityFeeGwei: entry.maxPriorityFeeGwei, + maxPriorityFeeWei: entry.maxPriorityFeeWei, + maxBlockLookBack: entry.maxBlockLookBack, + transactionConcurrency: entry.transactionConcurrency, + maxRetries: retryConfig?.retries || null, + retryDelay: retryConfig?.delay || null, + }, + paid: { + countVoters: Object.keys(paidPayoutWei).length, + totalRebateWei: paidTotalWei.toString(), + totalRebateEth: formatWeiToEthDecimalString(paidTotalWei), + }, + recomputed: { + countVoters: Object.keys(recomputedPayoutWei).length, + totalRebateWei: recomputedTotalWei.toString(), + totalRebateEth: formatWeiToEthDecimalString(recomputedTotalWei), + }, + deltas: { + positive, + zero, + negative, + positiveTotalWei: positiveTotalWei.toString(), + positiveTotalEth: formatWeiToEthDecimalString(positiveTotalWei), + negativeTotalWei: negativeTotalWei.toString(), + negativeTotalEth: formatWeiToEthDecimalString(negativeTotalWei), + }, + eventCollection: { + ...result.eventCollectionStats, + }, + anomalies: result.anomalies, + transactionEvidenceForPositiveDeltas: getPositiveDeltaEvidence(result, positive), + }); + } + + const expectedDeltaChecks = buildExpectedDeltaChecks(manifest, deltaByRebateAndAddress); + validateExpectedDeltaChecks(expectedDeltaChecks); + + const payout = buildCorrectionPayoutJson(manifest, consolidatedPayoutWei); + const consolidatedPayoutWeiStrings = Object.keys(consolidatedPayoutWei) + .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())) + .reduce((payoutWei: { [address: string]: string }, address) => { + payoutWei[address] = consolidatedPayoutWei[address].toString(); + return payoutWei; + }, {}); + const consolidatedTotalWei = totalWei(consolidatedPayoutWei); + const negativeDeltaCount = auditedRebates.reduce( + (count, rebateReport) => count + rebateReport.deltas.negative.length, + 0 + ); + const anomalyCount = auditedRebates.reduce((count, rebateReport) => count + rebateReport.anomalies.length, 0); + const report: CorrectionAuditReport = { + reportType: "VotingV2GasRebateCorrectionAudit", + generatedAt: generatedAt || new Date().toISOString(), + manifestPath: absoluteManifestPath, + manifestHash: getManifestHash(absoluteManifestPath), + manifestName: manifest.name, + outputPrefix: manifest.outputPrefix, + outputPaths: paths, + votingContractAddress: manifest.votingContractAddress, + customNodeUrlConfigured, + validation: { + passed: true, + expectedDeltaChecksPassed: true, + negativeDeltaCount, + anomalyCount, + }, + auditedRebates, + expectedDeltaChecks, + consolidatedTopUp: { + countVoters: Object.keys(consolidatedPayoutWei).length, + totalWei: consolidatedTotalWei.toString(), + totalEth: formatWeiToEthDecimalString(consolidatedTotalWei), + shareholderPayoutWei: consolidatedPayoutWeiStrings, + }, + }; + + fs.mkdirSync(path.resolve(outputDir), { recursive: true }); + fs.writeFileSync(paths.payoutPath, JSON.stringify(payout, null, 4)); + fs.writeFileSync(paths.auditJsonPath, JSON.stringify(report, null, 4)); + fs.writeFileSync(paths.auditMarkdownPath, formatCorrectionAuditMarkdown(report)); + + return { + ...paths, + payout, + report, + }; +} diff --git a/packages/affiliates/test/mocha-local/gas-rebate/VoterGasRebateV2Utils.js b/packages/affiliates/test/mocha-local/gas-rebate/VoterGasRebateV2Utils.js new file mode 100644 index 0000000000..d6ce979a15 --- /dev/null +++ b/packages/affiliates/test/mocha-local/gas-rebate/VoterGasRebateV2Utils.js @@ -0,0 +1,954 @@ +require("ts-node/register/transpile-only"); + +const { assert } = require("chai"); +const { BigNumber, utils } = require("ethers"); +const { createHash } = require("crypto"); +const fs = require("fs"); +const os = require("os"); +const path = require("path"); +const { + buildMonthlyAuditReport, + calculateVoterGasRebateV2, + getCorrectionArtifactPaths, + formatMonthlyAuditMarkdown, + getMonthlyAuditReportPaths, + loadCorrectionManifest, + parseEthDecimalToWei, + runVotingV2CorrectionAudit, + writeMonthlyAuditReports, +} = require("../../../gas-rebate/voterGasRebateV2Utils"); + +const votingAddress = "0x004395edb43EFca9885CEdad51EC9fAf93Bd34ac"; +const commitTopic = "0x0000000000000000000000000000000000000000000000000000000000000001"; +const revealTopic = "0x0000000000000000000000000000000000000000000000000000000000000002"; +const voter = "0x0000000000000000000000000000000000000001"; +const identifier = "0x5445535400000000000000000000000000000000000000000000000000000000"; +const ancillaryData = "0x"; +const correctionPositiveVoter = utils.getAddress("0x00000000000000000000000000000000000000e1"); +const correctionZeroVoter = utils.getAddress("0x00000000000000000000000000000000000000e2"); +const correctionNegativeVoter = utils.getAddress("0x00000000000000000000000000000000000000e3"); +const correctionNewVoter = utils.getAddress("0x00000000000000000000000000000000000000e4"); + +function makeVoteArgs(overrides = {}) { + return { + voter, + roundId: BigNumber.from(1), + identifier, + time: BigNumber.from(123), + ancillaryData, + numTokens: BigNumber.from(1000), + ...overrides, + }; +} + +function makeEvent(blockNumber, logIndex, transactionHash, args = makeVoteArgs()) { + return { + blockNumber, + logIndex, + transactionHash, + args, + }; +} + +function makeReceipt(transactionHash, from, blockNumber, gasUsed, effectiveGasPrice, eventTypes = []) { + return { + transactionHash, + from, + blockNumber, + gasUsed: BigNumber.from(gasUsed), + effectiveGasPrice: BigNumber.from(effectiveGasPrice), + logs: eventTypes.map((eventType) => ({ + address: votingAddress, + topics: [eventType === "commit" ? commitTopic : revealTopic], + })), + }; +} + +function makeVoting({ commitEvents, revealEvents, receipts, blocks, queryFilter }) { + const defaultQueryFilter = async (filter, fromBlock, toBlock) => { + const events = filter.eventName === "VoteCommitted" ? commitEvents : revealEvents; + return events.filter((event) => event.blockNumber >= fromBlock && event.blockNumber <= toBlock); + }; + + return { + address: votingAddress, + interface: { + getEventTopic: (eventName) => (eventName === "VoteCommitted" ? commitTopic : revealTopic), + }, + filters: { + VoteCommitted: () => ({ eventName: "VoteCommitted", topics: [commitTopic] }), + VoteRevealed: () => ({ eventName: "VoteRevealed", topics: [revealTopic] }), + }, + queryFilter: queryFilter || defaultQueryFilter, + provider: { + getTransactionReceipt: async (transactionHash) => receipts[transactionHash], + getBlock: async (blockNumber) => blocks[blockNumber], + }, + }; +} + +function makeMonthlyAuditConfig(overrides = {}) { + return { + minStakedTokens: "1000.0", + minStakedTokensWei: "1000000000000000000000", + maxPriorityFeeGwei: "0.001", + maxPriorityFeeWei: "1000000", + maxBlockLookBack: 250, + transactionConcurrency: 100, + maxRetries: 10, + retryDelay: 1000, + overrideFromBlockConfigured: true, + overrideToBlockConfigured: true, + customNodeUrlConfigured: true, + ...overrides, + }; +} + +function makeMonthlyAuditResult(overrides = {}) { + return { + votingContractAddress: votingAddress, + fromBlock: 24558868, + toBlock: 24781026, + minStakedTokens: BigNumber.from("1000000000000000000000"), + maxBlockLookBack: 250, + transactionConcurrency: 100, + maxPriorityFee: BigNumber.from("1000000"), + commitEvents: [makeEvent(1, 1, "0xcommit1"), makeEvent(2, 2, "0xcommit2")], + revealEvents: [makeEvent(3, 3, "0xreveal1"), makeEvent(4, 4, "0xreveal2"), makeEvent(5, 5, "0xreveal3")], + eligibleRevealEvents: [makeEvent(3, 3, "0xreveal1"), makeEvent(4, 4, "0xreveal2")], + matchingCommitEvents: [makeEvent(1, 1, "0xcommit1")], + transactionsToRefund: [ + makeReceipt("0xcommit1", voter, 1, "100", "200", ["commit"]), + makeReceipt("0xreveal1", voter, 3, "50", "200", ["reveal"]), + ], + shareholderPayoutWei: { + [voter]: BigNumber.from("1234567890000000000"), + }, + totalRebateWei: BigNumber.from("1234567890000000000"), + transactionEvidence: [ + { + transactionHash: "0xcommit1", + from: voter, + blockNumber: 1, + gasUsed: "100", + effectiveGasPrice: "200", + baseFee: "100", + actualPriorityFee: "100", + cappedPriorityFee: "100", + effectiveGasPriceForRebate: "200", + rebateWei: "20000", + }, + ], + eventCollectionStats: { + maxBlockLookBack: 250, + minBlockLookBack: 1, + rangesQueried: 889, + queryAttempts: 1778, + retryCount: 1, + splitCount: 2, + validationFailures: 2, + providerErrors: 1, + receiptValidationCount: 345, + commitEventCount: 2, + revealEventCount: 3, + validationPassed: true, + }, + anomalies: [ + { + type: "reveal_missing_commit", + message: "Eligible reveal has no matching commit", + fromBlock: 24558868, + toBlock: 24781026, + transactionHash: "0xreveal2", + voter, + }, + ], + ...overrides, + }; +} + +function writeJson(filePath, value) { + fs.mkdirSync(path.dirname(filePath), { recursive: true }); + fs.writeFileSync(filePath, JSON.stringify(value, null, 2)); +} + +function makePaidRebate(overrides = {}) { + return { + votingContractAddress: votingAddress, + rebate: 66, + fromBlock: 100, + toBlock: 200, + countVoters: 3, + totalRebateAmount: 6, + shareholderPayout: { + [correctionPositiveVoter]: 1, + [correctionZeroVoter]: 2, + [correctionNegativeVoter]: 3, + }, + ...overrides, + }; +} + +function makeCorrectionManifest(overrides = {}, auditOverrides = {}) { + return { + version: 1, + name: "Test correction", + votingContractAddress: votingAddress, + outputPrefix: "Correction_Test", + audits: [ + { + rebateFile: "paid/Rebate_66.json", + rebateNumber: 66, + fromBlock: 100, + toBlock: 200, + minStakedTokens: "1000", + maxPriorityFeeGwei: "0.001", + maxBlockLookBack: 250, + transactionConcurrency: 10, + ...auditOverrides, + }, + ], + expectedDeltas: [], + ...overrides, + }; +} + +function sumBigNumbers(values) { + return Object.values(values).reduce((total, amount) => total.add(amount), BigNumber.from(0)); +} + +function makeCorrectionComputationResult(shareholderPayoutWei, overrides = {}) { + return makeMonthlyAuditResult({ + votingContractAddress: votingAddress, + fromBlock: 100, + toBlock: 200, + shareholderPayoutWei, + totalRebateWei: sumBigNumbers(shareholderPayoutWei), + transactionEvidence: [ + { + transactionHash: "0xpositive", + from: correctionPositiveVoter, + blockNumber: 101, + gasUsed: "1", + effectiveGasPrice: "1", + baseFee: "1", + actualPriorityFee: "0", + cappedPriorityFee: "0", + effectiveGasPriceForRebate: "1", + rebateWei: "1", + }, + { + transactionHash: "0xnew", + from: correctionNewVoter, + blockNumber: 102, + gasUsed: "1", + effectiveGasPrice: "1", + baseFee: "1", + actualPriorityFee: "0", + cappedPriorityFee: "0", + effectiveGasPriceForRebate: "1", + rebateWei: "1", + }, + { + transactionHash: "0xnegative", + from: correctionNegativeVoter, + blockNumber: 103, + gasUsed: "1", + effectiveGasPrice: "1", + baseFee: "1", + actualPriorityFee: "0", + cappedPriorityFee: "0", + effectiveGasPriceForRebate: "1", + rebateWei: "1", + }, + ], + anomalies: [], + ...overrides, + }); +} + +describe("VoterGasRebateV2 utils", function () { + it("uses deterministic event ordering before commit dedupe and returns exact wei totals", async function () { + const recipient = "0x00000000000000000000000000000000000000a1"; + const earlyCommit = makeEvent(5, 1, "0xcommit"); + const lateCommit = makeEvent(10, 2, "0xlate"); + const reveal = makeEvent(12, 3, "0xreveal"); + const voting = makeVoting({ + commitEvents: [lateCommit, earlyCommit], + revealEvents: [reveal], + receipts: { + "0xcommit": makeReceipt("0xcommit", recipient, 5, 10, 150, ["commit"]), + "0xlate": makeReceipt("0xlate", recipient, 10, 1000, 150, ["commit"]), + "0xreveal": makeReceipt("0xreveal", recipient, 12, 5, 110, ["reveal"]), + }, + blocks: { + 5: { baseFeePerGas: BigNumber.from(100) }, + 12: { baseFeePerGas: BigNumber.from(100) }, + }, + }); + + const result = await calculateVoterGasRebateV2({ + voting, + fromBlock: 1, + toBlock: 20, + minTokens: BigNumber.from(500), + maxBlockLookBack: 100, + transactionConcurrency: 2, + maxPriorityFee: BigNumber.from(20), + }); + + assert.equal(result.matchingCommitEvents.length, 1); + assert.equal(result.matchingCommitEvents[0].transactionHash, "0xcommit"); + assert.deepEqual( + result.transactionsToRefund.map((transaction) => transaction.transactionHash), + ["0xcommit", "0xreveal"] + ); + assert.equal(result.shareholderPayoutWei[recipient].toString(), "1750"); + assert.equal(result.totalRebateWei.toString(), "1750"); + assert.deepEqual( + result.transactionEvidence.map((transaction) => transaction.rebateWei), + ["1200", "550"] + ); + }); + + it("dedupes receipts by transaction hash before calculating rebates", async function () { + const recipient = "0x00000000000000000000000000000000000000b1"; + const commit = makeEvent(5, 1, "0xshared"); + const reveal = makeEvent(6, 2, "0xshared"); + const voting = makeVoting({ + commitEvents: [commit], + revealEvents: [reveal], + receipts: { + "0xshared": makeReceipt("0xshared", recipient, 6, 7, 150, ["commit", "reveal"]), + }, + blocks: { + 6: { baseFeePerGas: BigNumber.from(100) }, + }, + }); + + const result = await calculateVoterGasRebateV2({ + voting, + fromBlock: 1, + toBlock: 20, + minTokens: BigNumber.from(500), + maxBlockLookBack: 100, + transactionConcurrency: 2, + maxPriorityFee: null, + }); + + assert.equal(result.transactionsToRefund.length, 1); + assert.equal(result.shareholderPayoutWei[recipient].toString(), "1050"); + assert.equal(result.totalRebateWei.toString(), "1050"); + }); + + it("splits and retries when receipt validation catches silently truncated events", async function () { + const recipient = "0x00000000000000000000000000000000000000c1"; + const commit = makeEvent(2, 1, "0xshared"); + const reveal = makeEvent(2, 2, "0xshared"); + let truncatedRevealQueries = 0; + const queryFilter = async (filter, fromBlock, toBlock) => { + const events = filter.eventName === "VoteCommitted" ? [commit] : [reveal]; + if (filter.eventName === "VoteRevealed" && fromBlock === 1 && toBlock === 4) { + truncatedRevealQueries++; + return []; + } + return events.filter((event) => event.blockNumber >= fromBlock && event.blockNumber <= toBlock); + }; + const voting = makeVoting({ + commitEvents: [commit], + revealEvents: [reveal], + receipts: { + "0xshared": makeReceipt("0xshared", recipient, 2, 7, 150, ["commit", "reveal"]), + }, + blocks: { + 2: { baseFeePerGas: BigNumber.from(100) }, + }, + queryFilter, + }); + + const result = await calculateVoterGasRebateV2({ + voting, + fromBlock: 1, + toBlock: 4, + minTokens: BigNumber.from(500), + maxBlockLookBack: 4, + transactionConcurrency: 2, + maxPriorityFee: null, + }); + + assert.equal(truncatedRevealQueries, 1); + assert.equal(result.eventCollectionStats.validationPassed, true); + assert.equal(result.eventCollectionStats.validationFailures, 1); + assert.equal(result.eventCollectionStats.splitCount, 1); + assert.equal(result.commitEvents.length, 1); + assert.equal(result.revealEvents.length, 1); + assert.isTrue(result.anomalies.some((anomaly) => anomaly.type === "receipt_event_count_mismatch")); + assert.equal(result.transactionsToRefund.length, 1); + assert.equal(result.shareholderPayoutWei[recipient].toString(), "1050"); + }); + + it("fails closed when event truncation persists at the minimum block range", async function () { + const recipient = "0x00000000000000000000000000000000000000d1"; + const commit = makeEvent(1, 1, "0xtruncated"); + const reveal = makeEvent(1, 2, "0xtruncated"); + const queryFilter = async (filter, fromBlock, toBlock) => { + const events = filter.eventName === "VoteCommitted" ? [commit] : [reveal]; + if (filter.eventName === "VoteRevealed") return []; + return events.filter((event) => event.blockNumber >= fromBlock && event.blockNumber <= toBlock); + }; + const voting = makeVoting({ + commitEvents: [commit], + revealEvents: [reveal], + receipts: { + "0xtruncated": makeReceipt("0xtruncated", recipient, 1, 7, 150, ["commit", "reveal"]), + }, + blocks: { + 1: { baseFeePerGas: BigNumber.from(100) }, + }, + queryFilter, + }); + + try { + await calculateVoterGasRebateV2({ + voting, + fromBlock: 1, + toBlock: 1, + minTokens: BigNumber.from(500), + maxBlockLookBack: 1, + transactionConcurrency: 2, + maxPriorityFee: null, + }); + assert.fail("Expected event collection validation to fail"); + } catch (error) { + assert.equal(error.name, "EventCollectionValidationError"); + assert.equal(error.eventCollectionStats.validationPassed, false); + assert.equal(error.eventCollectionStats.validationFailures, 1); + assert.isTrue(error.anomalies.some((anomaly) => anomaly.type === "receipt_event_count_mismatch")); + } + }); + + it("builds monthly audit reports with required counts, config, validation, and exact wei totals", function () { + const rpcUrl = "https://rpc.example.invalid/secret-key"; + const report = buildMonthlyAuditReport(makeMonthlyAuditResult(), { + outputRebateFilePath: "/tmp/Rebate_66.json", + rebateNumber: 66, + generatedAt: "2026-04-01T00:00:00.000Z", + config: makeMonthlyAuditConfig(), + }); + + assert.equal(report.reportType, "VotingV2MonthlyGasRebateAudit"); + assert.equal(report.outputRebateFilePath, "/tmp/Rebate_66.json"); + assert.equal(report.votingContractAddress, votingAddress); + assert.deepEqual(report.blockRange, { fromBlock: 24558868, toBlock: 24781026 }); + assert.deepEqual(report.counts, { + commitEvents: 2, + revealEvents: 3, + eligibleRevealEvents: 2, + matchedCommitEvents: 1, + transactions: 2, + voters: 1, + }); + assert.equal(report.payout.totalRebateWei, "1234567890000000000"); + assert.equal(report.payout.totalRebateEth, "1.23456789"); + assert.equal(report.eventCollection.maxBlockLookBack, 250); + assert.equal(report.eventCollection.retryCount, 1); + assert.equal(report.eventCollection.splitCount, 2); + assert.equal(report.validation.passed, true); + assert.equal(report.validation.anomalyCount, 1); + assert.equal(report.transactionEvidence[0].transactionHash, "0xcommit1"); + assert.equal(report.effectiveConfig.customNodeUrlConfigured, true); + assert.notProperty(report.effectiveConfig, "customNodeUrl"); + assert.notInclude(JSON.stringify(report), rpcUrl); + }); + + it("formats concise monthly audit Markdown from the JSON report object", function () { + const markdown = formatMonthlyAuditMarkdown( + buildMonthlyAuditReport(makeMonthlyAuditResult(), { + outputRebateFilePath: "/tmp/Rebate_66.json", + rebateNumber: 66, + generatedAt: "2026-04-01T00:00:00.000Z", + config: makeMonthlyAuditConfig(), + }) + ); + + assert.include(markdown, "# VotingV2 Monthly Gas Rebate Audit - Rebate 66"); + assert.include(markdown, "Output rebate file: `/tmp/Rebate_66.json`"); + assert.include(markdown, "- Eligible reveal events: 2"); + assert.include(markdown, "- Matched commit events: 1"); + assert.include(markdown, "- Total payout: 1234567890000000000 wei (1.23456789 ETH)"); + assert.include(markdown, "- Validation passed: true"); + assert.include(markdown, "- Retry count: 1"); + assert.include(markdown, "- Split count: 2"); + assert.include(markdown, "- Custom node URL configured: true"); + assert.notInclude(markdown, "secret-key"); + }); + + it("writes monthly audit JSON and Markdown next to the rebate file", function () { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "voter-gas-rebate-v2-audit-")); + try { + const outputRebateFilePath = path.join(tempDir, "Rebate_66.json"); + const paths = getMonthlyAuditReportPaths(outputRebateFilePath); + const written = writeMonthlyAuditReports(makeMonthlyAuditResult(), { + outputRebateFilePath, + rebateNumber: 66, + generatedAt: "2026-04-01T00:00:00.000Z", + config: makeMonthlyAuditConfig(), + }); + + assert.deepEqual(written.jsonPath, paths.jsonPath); + assert.deepEqual(written.markdownPath, paths.markdownPath); + assert.equal(path.basename(written.jsonPath), "Rebate_66.audit.json"); + assert.equal(path.basename(written.markdownPath), "Rebate_66.audit.md"); + assert.isTrue(fs.existsSync(written.jsonPath)); + assert.isTrue(fs.existsSync(written.markdownPath)); + + const jsonReport = JSON.parse(fs.readFileSync(written.jsonPath, "utf8")); + const markdownReport = fs.readFileSync(written.markdownPath, "utf8"); + assert.equal(jsonReport.payout.totalRebateWei, "1234567890000000000"); + assert.include(markdownReport, "VotingV2 Monthly Gas Rebate Audit"); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + + it("parses paid ETH decimals to exact wei", function () { + assert.equal(parseEthDecimalToWei("0.007088051537280779").toString(), "7088051537280779"); + assert.equal(parseEthDecimalToWei(1e-7).toString(), "100000000000"); + }); + + it("fails correction manifest validation for missing, malformed, and invalid inputs", function () { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "voter-gas-rebate-v2-correction-validation-")); + try { + assert.throws( + () => loadCorrectionManifest(path.join(tempDir, "missing.json"), { baseDir: tempDir }), + /Correction manifest .* not found/ + ); + + const malformedManifestPath = path.join(tempDir, "malformed.json"); + fs.writeFileSync(malformedManifestPath, "{"); + assert.throws(() => loadCorrectionManifest(malformedManifestPath, { baseDir: tempDir }), /malformed JSON/); + + const paidPath = path.join(tempDir, "paid/Rebate_66.json"); + const manifestPath = path.join(tempDir, "manifest.json"); + writeJson(paidPath, makePaidRebate()); + + writeJson( + manifestPath, + makeCorrectionManifest({ + votingContractAddress: "0x0000000000000000000000000000000000000999", + }) + ); + assert.throws( + () => + loadCorrectionManifest(manifestPath, { + baseDir: tempDir, + expectedVotingContractAddress: votingAddress, + }), + /non-VotingV2/ + ); + + writeJson(manifestPath, makeCorrectionManifest({}, { fromBlock: 201, toBlock: 200 })); + assert.throws(() => loadCorrectionManifest(manifestPath, { baseDir: tempDir }), /invalid block range/); + + writeJson(manifestPath, makeCorrectionManifest({}, { rebateFile: "paid/Does_Not_Exist.json" })); + assert.throws(() => loadCorrectionManifest(manifestPath, { baseDir: tempDir }), /Paid rebate file .* not found/); + + writeJson(paidPath, { ...makePaidRebate(), shareholderPayout: undefined }); + writeJson(manifestPath, makeCorrectionManifest()); + assert.throws( + () => loadCorrectionManifest(manifestPath, { baseDir: tempDir }), + /shareholderPayout must be an object/ + ); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + + it("fails correction manifests with overlapping audit block ranges", function () { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "voter-gas-rebate-v2-correction-overlap-")); + try { + writeJson(path.join(tempDir, "paid/Rebate_66.json"), makePaidRebate()); + writeJson( + path.join(tempDir, "paid/Rebate_67.json"), + makePaidRebate({ + rebate: 67, + fromBlock: 200, + toBlock: 300, + }) + ); + const manifestPath = path.join(tempDir, "manifest.json"); + const manifest = makeCorrectionManifest({ + audits: [ + makeCorrectionManifest().audits[0], + { + ...makeCorrectionManifest().audits[0], + rebateFile: "paid/Rebate_67.json", + rebateNumber: 67, + fromBlock: 200, + toBlock: 300, + }, + ], + }); + writeJson(manifestPath, manifest); + + assert.throws(() => loadCorrectionManifest(manifestPath, { baseDir: tempDir }), /block ranges overlap/); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + + it("consolidates positive correction deltas and reports zero and negative deltas separately", async function () { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "voter-gas-rebate-v2-correction-run-")); + try { + const manifestPath = path.join(tempDir, "manifest.json"); + const outputDir = path.join(tempDir, "out"); + writeJson(path.join(tempDir, "paid/Rebate_66.json"), makePaidRebate()); + writeJson( + manifestPath, + makeCorrectionManifest({ + expectedDeltas: [ + { + rebateNumber: 66, + address: correctionPositiveVoter, + deltaWei: "500000000000000000", + }, + { + rebateNumber: 66, + address: correctionNegativeVoter, + deltaWei: "-2000000000000000000", + }, + ], + }) + ); + + const recomputedPayoutWei = { + [correctionPositiveVoter]: BigNumber.from("1500000000000000000"), + [correctionZeroVoter]: BigNumber.from("2000000000000000000"), + [correctionNegativeVoter]: BigNumber.from("1000000000000000000"), + [correctionNewVoter]: BigNumber.from("250000000000000000"), + }; + const written = await runVotingV2CorrectionAudit({ + manifestPath, + voting: { address: votingAddress }, + outputDir, + baseDir: tempDir, + generatedAt: "2026-04-01T00:00:00.000Z", + customNodeUrlConfigured: true, + calculateRebate: async (config) => { + assert.equal(config.fromBlock, 100); + assert.equal(config.toBlock, 200); + assert.equal(config.minTokens.toString(), "1000000000000000000000"); + assert.equal(config.maxPriorityFee.toString(), "1000000"); + assert.equal(config.maxBlockLookBack, 250); + assert.equal(config.transactionConcurrency, 10); + return makeCorrectionComputationResult(recomputedPayoutWei); + }, + }); + + assert.isTrue(fs.existsSync(written.payoutPath)); + assert.isTrue(fs.existsSync(written.auditJsonPath)); + assert.isTrue(fs.existsSync(written.auditMarkdownPath)); + assert.equal(written.payout.countVoters, 2); + assert.equal(written.payout.totalRebateAmount, 0.75); + assert.deepEqual(written.payout.shareholderPayout, { + [correctionPositiveVoter]: 0.5, + [correctionNewVoter]: 0.25, + }); + assert.notProperty(written.payout.shareholderPayout, correctionNegativeVoter); + assert.equal(written.report.consolidatedTopUp.totalWei, "750000000000000000"); + assert.equal(written.report.auditedRebates[0].deltas.positive.length, 2); + assert.equal(written.report.auditedRebates[0].deltas.zero.length, 1); + assert.equal(written.report.auditedRebates[0].deltas.negative.length, 1); + assert.equal(written.report.auditedRebates[0].deltas.negative[0].address, correctionNegativeVoter); + assert.equal(written.report.auditedRebates[0].deltas.negative[0].deltaWei, "-2000000000000000000"); + assert.deepEqual( + written.report.auditedRebates[0].transactionEvidenceForPositiveDeltas.map( + (evidence) => evidence.transactionHash + ), + ["0xpositive", "0xnew"] + ); + assert.isTrue(written.report.expectedDeltaChecks.every((check) => check.passed)); + assert.equal(written.report.customNodeUrlConfigured, true); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + + it("fails exact expected-delta mismatches before writing correction outputs", async function () { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "voter-gas-rebate-v2-correction-expected-")); + try { + const manifestPath = path.join(tempDir, "manifest.json"); + const outputDir = path.join(tempDir, "out"); + writeJson(path.join(tempDir, "paid/Rebate_66.json"), makePaidRebate()); + writeJson( + manifestPath, + makeCorrectionManifest({ + expectedDeltas: [ + { + rebateNumber: 66, + address: correctionPositiveVoter, + deltaWei: "1", + }, + ], + }) + ); + const paths = getCorrectionArtifactPaths(outputDir, "Correction_Test"); + const recomputedPayoutWei = { + [correctionPositiveVoter]: BigNumber.from("1500000000000000000"), + [correctionZeroVoter]: BigNumber.from("2000000000000000000"), + [correctionNegativeVoter]: BigNumber.from("3000000000000000000"), + }; + + try { + await runVotingV2CorrectionAudit({ + manifestPath, + voting: { address: votingAddress }, + outputDir, + baseDir: tempDir, + calculateRebate: async () => makeCorrectionComputationResult(recomputedPayoutWei), + }); + assert.fail("Expected exact delta validation to fail"); + } catch (error) { + assert.match(error.message, /Expected delta mismatch/); + } + + assert.isFalse(fs.existsSync(paths.payoutPath)); + assert.isFalse(fs.existsSync(paths.auditJsonPath)); + assert.isFalse(fs.existsSync(paths.auditMarkdownPath)); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + + it("refuses to overwrite existing correction outputs unless explicitly allowed", async function () { + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "voter-gas-rebate-v2-correction-overwrite-")); + try { + const manifestPath = path.join(tempDir, "manifest.json"); + const outputDir = path.join(tempDir, "out"); + writeJson(path.join(tempDir, "paid/Rebate_66.json"), makePaidRebate()); + writeJson(manifestPath, makeCorrectionManifest()); + const paths = getCorrectionArtifactPaths(outputDir, "Correction_Test"); + writeJson(paths.payoutPath, { existing: true }); + + let calculatorCalled = false; + try { + await runVotingV2CorrectionAudit({ + manifestPath, + voting: { address: votingAddress }, + outputDir, + baseDir: tempDir, + calculateRebate: async () => { + calculatorCalled = true; + return makeCorrectionComputationResult({}); + }, + }); + assert.fail("Expected overwrite protection to fail"); + } catch (error) { + assert.match(error.message, /Refusing to overwrite/); + } + + assert.equal(calculatorCalled, false); + } finally { + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); + + it("loads the committed March 2026 Rebate 66 correction manifest", function () { + const affiliatesDir = path.resolve(__dirname, "../../.."); + const manifestPath = path.join(affiliatesDir, "gas-rebate/corrections/Rebate_66_Correction_Manifest.json"); + const manifest = loadCorrectionManifest(manifestPath, { + baseDir: affiliatesDir, + expectedVotingContractAddress: votingAddress, + }); + + assert.equal(manifest.name, "March 2026 Rebate 66 VotingV2 correction"); + assert.equal(manifest.outputPrefix, "Correction_Rebate_66"); + assert.equal(manifest.votingContractAddress, votingAddress); + assert.lengthOf(manifest.audits, 1); + assert.include(manifest.audits[0], { + rebateFile: "gas-rebate/rebates/Rebate_66.json", + rebateNumber: 66, + fromBlock: 24558868, + toBlock: 24781026, + minStakedTokens: "1000", + maxPriorityFeeGwei: "0.001", + maxBlockLookBack: 250, + transactionConcurrency: 100, + }); + assert.equal(manifest.audits[0].paidRebate.countVoters, 634); + assert.equal(manifest.audits[0].paidRebate.totalRebateAmount, 2.0729797831799184); + assert.deepEqual( + manifest.expectedDeltas.map((delta) => ({ + rebateNumber: delta.rebateNumber, + address: delta.address, + deltaWei: delta.deltaWei, + })), + [ + { + rebateNumber: 66, + address: utils.getAddress("0xf20737e48160a87dc9d1b26d8b63c796d2f1ea91"), + deltaWei: "7088051537280779", + }, + { + rebateNumber: 66, + address: utils.getAddress("0x2a9437de0ccd4fd7b7d98831213acedefc7a1092"), + deltaWei: "1902006430166225", + }, + ] + ); + }); + + it("loads the committed Phase 6 Rebate 65-66 correction manifest with per-rebate policy parameters", function () { + const affiliatesDir = path.resolve(__dirname, "../../.."); + const manifestPath = path.join(affiliatesDir, "gas-rebate/corrections/Rebates_65_66_Correction_Manifest.json"); + const manifest = loadCorrectionManifest(manifestPath, { + baseDir: affiliatesDir, + expectedVotingContractAddress: votingAddress, + }); + + assert.equal(manifest.name, "March and February 2026 Rebate 65-66 VotingV2 correction audit"); + assert.equal(manifest.outputPrefix, "Correction_Rebates_65_66"); + assert.lengthOf(manifest.audits, 2); + assert.deepEqual( + manifest.audits.map((audit) => ({ + rebateFile: audit.rebateFile, + rebateNumber: audit.rebateNumber, + fromBlock: audit.fromBlock, + toBlock: audit.toBlock, + minStakedTokens: audit.minStakedTokens, + maxPriorityFeeGwei: audit.maxPriorityFeeGwei, + maxBlockLookBack: audit.maxBlockLookBack, + transactionConcurrency: audit.transactionConcurrency, + })), + [ + { + rebateFile: "gas-rebate/rebates/Rebate_66.json", + rebateNumber: 66, + fromBlock: 24558868, + toBlock: 24781026, + minStakedTokens: "1000", + maxPriorityFeeGwei: "0.001", + maxBlockLookBack: 250, + transactionConcurrency: 100, + }, + { + rebateFile: "gas-rebate/rebates/Rebate_65.json", + rebateNumber: 65, + fromBlock: 24358293, + toBlock: 24558867, + minStakedTokens: "1000", + maxPriorityFeeGwei: "0.001", + maxBlockLookBack: 250, + transactionConcurrency: 100, + }, + ] + ); + assert.include(manifest.audits[1].notes, "backward audit stop point"); + assert.deepEqual( + manifest.expectedDeltas.map((delta) => delta.rebateNumber), + [66, 66] + ); + }); + + it("keeps committed Rebate 66 correction artifacts reviewable without committed audit JSON", function () { + const affiliatesDir = path.resolve(__dirname, "../../.."); + const outputDir = path.join(affiliatesDir, "gas-rebate/corrections"); + const paths = getCorrectionArtifactPaths(outputDir, "Correction_Rebate_66"); + + assert.isTrue(fs.existsSync(paths.payoutPath)); + assert.isTrue(fs.existsSync(paths.auditMarkdownPath)); + + const payout = JSON.parse(fs.readFileSync(paths.payoutPath, "utf8")); + const markdown = fs.readFileSync(paths.auditMarkdownPath, "utf8"); + + assert.equal(payout.votingContractAddress, votingAddress); + assert.equal(payout.rebate, 66); + assert.equal(payout.fromBlock, 24558868); + assert.equal(payout.toBlock, 24781026); + assert.equal(payout.countVoters, 585); + assert.equal(Object.keys(payout.shareholderPayout).length, payout.countVoters); + + for (const expected of [ + { + address: utils.getAddress("0xf20737e48160a87dc9d1b26d8b63c796d2f1ea91"), + deltaWei: "7088051537280779", + deltaEth: 0.007088051537280779, + }, + { + address: utils.getAddress("0x2a9437de0ccd4fd7b7d98831213acedefc7a1092"), + deltaWei: "1902006430166225", + deltaEth: 0.001902006430166225, + }, + ]) { + assert.equal(payout.shareholderPayout[expected.address], expected.deltaEth); + assert.include(markdown, `${expected.address}: expected ${expected.deltaWei}, actual ${expected.deltaWei}`); + assert.include(markdown, "passed true"); + } + + assert.include(markdown, "# VotingV2 Gas Rebate Correction Audit - March 2026 Rebate 66 VotingV2 correction"); + assert.include(markdown, "- Total: 1095766860809837881 wei (1.095766860809837881 ETH)"); + assert.include(markdown, "- Voters: 585"); + assert.include(markdown, "- Positive delta count: 585"); + assert.include(markdown, "- Negative delta count: 0"); + assert.include(markdown, "- Event validation passed: true"); + }); + + it("keeps committed Phase 6 Rebate 65-66 correction artifacts reviewable without committed audit JSON", function () { + const affiliatesDir = path.resolve(__dirname, "../../.."); + const outputDir = path.join(affiliatesDir, "gas-rebate/corrections"); + const manifestPath = path.join(outputDir, "Rebates_65_66_Correction_Manifest.json"); + const paths = getCorrectionArtifactPaths(outputDir, "Correction_Rebates_65_66"); + + assert.isTrue(fs.existsSync(paths.payoutPath)); + assert.isTrue(fs.existsSync(paths.auditMarkdownPath)); + + const payout = JSON.parse(fs.readFileSync(paths.payoutPath, "utf8")); + const markdown = fs.readFileSync(paths.auditMarkdownPath, "utf8"); + const manifestHash = createHash("sha256").update(fs.readFileSync(manifestPath)).digest("hex"); + + assert.equal(payout.votingContractAddress, votingAddress); + assert.equal(payout.rebate, 65); + assert.equal(payout.fromBlock, 24358293); + assert.equal(payout.toBlock, 24781026); + assert.equal(payout.countVoters, 591); + assert.equal(Object.keys(payout.shareholderPayout).length, payout.countVoters); + assert.include(markdown, "# VotingV2 Gas Rebate Correction Audit - March and February 2026"); + assert.include(markdown, `Manifest SHA-256: \`${manifestHash}\``); + assert.include(markdown, "### Rebate 66"); + assert.include(markdown, "### Rebate 65"); + assert.include(markdown, "- Notes: February 2026 backward audit stop point"); + assert.include(markdown, "- Positive delta total: 58 wei (0.000000000000000058 ETH)"); + assert.include(markdown, "- Negative delta total: -52 wei (-0.000000000000000052 ETH)"); + assert.include(markdown, "- Split count: 0"); + assert.include(markdown, "- Total: 1095766860809837939 wei (1.095766860809837939 ETH)"); + }); + + it("documents the Phase 7 runbook and review checklist without concrete RPC URLs", function () { + const affiliatesDir = path.resolve(__dirname, "../../.."); + const readme = fs.readFileSync(path.join(affiliatesDir, "gas-rebate/README.md"), "utf8"); + + for (const requiredText of [ + "Safe Chunk Size and Validation", + "`MAX_BLOCK_LOOK_BACK=250` is the safe default chunk size", + "CUSTOM_NODE_URL=\"\"", + "March 2026 Rebate 66 Rerun", + "Correction/audit mode is VotingV2-only", + "Historical `Rebate_*.json` files are immutable", + "Correction Manifest Schema", + "March 2026 Correction Audit", + "Overpayments are not clawed back by this workflow", + "Artifact Review Checklist", + "PR Checklist", + "No secrets committed", + "Expected deltas pass", + "Validation passed", + "Generated payout total equals audit summary total", + "Historical rebates unchanged", + ]) { + assert.include(readme, requiredText); + } + + assert.notMatch(readme, /CUSTOM_NODE_URL=["']?https?:\/\//); + assert.notInclude(readme, "secret-key"); + }); +}); From 6bfb53c06fad6d2e044be64124867170cb0d2592 Mon Sep 17 00:00:00 2001 From: Pablo Maldonado Date: Wed, 29 Apr 2026 16:22:41 +0000 Subject: [PATCH 2/5] fix(gas-rebates): set safer monthly defaults --- packages/affiliates/gas-rebate/README.md | 12 ++++++------ packages/affiliates/gas-rebate/VoterGasRebateV2.ts | 10 ++++++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/affiliates/gas-rebate/README.md b/packages/affiliates/gas-rebate/README.md index 4fd58aa3e8..8ef27c00e7 100644 --- a/packages/affiliates/gas-rebate/README.md +++ b/packages/affiliates/gas-rebate/README.md @@ -36,7 +36,7 @@ OVERRIDE_TO_BLOCK=18500000 \ MIN_STAKED_TOKENS=1000 \ yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet -# With priority fee cap (optional) +# Override the default priority fee cap CUSTOM_NODE_URL="" \ MAX_PRIORITY_FEE_GWEI=0.001 \ yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet @@ -48,8 +48,8 @@ yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet | ------------------------- | ------------------------------------------------------------------------ | ----------------------------------------- | | `OVERRIDE_FROM_BLOCK` | Start block number (overrides automatic date-based calculation) | Auto-calculated from previous month start | | `OVERRIDE_TO_BLOCK` | End block number (overrides automatic date-based calculation) | Auto-calculated from previous month end | -| `MIN_STAKED_TOKENS` | Minimum UMA tokens staked to be eligible for rebate | `500` | -| `MAX_PRIORITY_FEE_GWEI` | Maximum priority fee to refund (in gwei). If not set, no cap is applied. | None (no cap) | +| `MIN_STAKED_TOKENS` | Minimum UMA tokens staked to be eligible for rebate | `1000` | +| `MAX_PRIORITY_FEE_GWEI` | Maximum priority fee to refund (in gwei) | `0.001` | | `MAX_BLOCK_LOOK_BACK` | Maximum block range for VotingV2 event queries | `250` | | `TRANSACTION_CONCURRENCY` | Number of concurrent RPC requests for fetching transactions/blocks | `50` | | `MAX_RETRIES` | Maximum retry attempts for failed RPC calls | `10` | @@ -230,16 +230,16 @@ Overpayments are not clawed back by this workflow. Report zero and negative delt - Generated payout total equals audit summary total. - Historical rebates unchanged. -### Priority Fee Capping (Optional) +### Priority Fee Capping -By default, the script rebates the full gas cost including any priority fee. You can optionally cap the priority fee (tip) portion to prevent rebating excessive tips by setting `MAX_PRIORITY_FEE_GWEI`. +By default, the script fully rebates base fee and caps the priority fee (tip) portion at `0.001` gwei. You can override the cap by setting `MAX_PRIORITY_FEE_GWEI`. For example, with `MAX_PRIORITY_FEE_GWEI=0.001`: - If a voter paid a 0.0005 gwei priority fee, they get rebated the full 0.0005 gwei - If a voter paid a 0.002 gwei priority fee, they only get rebated 0.001 gwei -The base fee is always fully rebated. Enabling a cap can encourage voters to use reasonable gas settings while still covering network costs. +The base fee is always fully rebated. The default cap encourages voters to use reasonable gas settings while still covering network costs. ## Legacy Scripts diff --git a/packages/affiliates/gas-rebate/VoterGasRebateV2.ts b/packages/affiliates/gas-rebate/VoterGasRebateV2.ts index b096deee80..8524151c79 100644 --- a/packages/affiliates/gas-rebate/VoterGasRebateV2.ts +++ b/packages/affiliates/gas-rebate/VoterGasRebateV2.ts @@ -26,6 +26,9 @@ const { MAX_BLOCK_LOOK_BACK, } = process.env; +const DEFAULT_MIN_STAKED_TOKENS = "1000"; +const DEFAULT_MAX_PRIORITY_FEE_GWEI = "0.001"; + export async function run(): Promise { console.log("Running UMA2.0 Gas rebate script! This script assumes you are running it for the previous month๐ŸŒ."); @@ -52,8 +55,11 @@ export async function run(): Promise { : (await findBlockNumberAtTimestamp(getWeb3(), prevMonthEnd.getTime() / 1000)).blockNumber; // Minimum UMA tokens staked to be eligible for a rebate - const minTokens = ethers.utils.parseEther(MIN_STAKED_TOKENS ? MIN_STAKED_TOKENS : "500"); - const maxPriorityFee = MAX_PRIORITY_FEE_GWEI ? ethers.utils.parseUnits(MAX_PRIORITY_FEE_GWEI, "gwei") : null; + const minTokens = ethers.utils.parseEther(MIN_STAKED_TOKENS ? MIN_STAKED_TOKENS : DEFAULT_MIN_STAKED_TOKENS); + const maxPriorityFee = ethers.utils.parseUnits( + MAX_PRIORITY_FEE_GWEI ? MAX_PRIORITY_FEE_GWEI : DEFAULT_MAX_PRIORITY_FEE_GWEI, + "gwei" + ); const maxBlockLookBack = MAX_BLOCK_LOOK_BACK ? Number(MAX_BLOCK_LOOK_BACK) : 250; const retryConfig = { retries: MAX_RETRIES ? Number(MAX_RETRIES) : 10, From f7679dda4e26492b46d50ec6bb7ed8edd8b18297 Mon Sep 17 00:00:00 2001 From: Pablo Maldonado Date: Thu, 30 Apr 2026 10:40:30 +0000 Subject: [PATCH 3/5] fix(gas-rebates): add rebate 66 correction payout --- .../corrections/Correction_Rebate_66.audit.md | 39 ++ .../corrections/Correction_Rebate_66.json | 595 ++++++++++++++++++ .../Rebate_66_Correction_Manifest.json | 30 + 3 files changed, 664 insertions(+) create mode 100644 packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.audit.md create mode 100644 packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json create mode 100644 packages/affiliates/gas-rebate/corrections/Rebate_66_Correction_Manifest.json diff --git a/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.audit.md b/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.audit.md new file mode 100644 index 0000000000..4456534f3f --- /dev/null +++ b/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.audit.md @@ -0,0 +1,39 @@ +# VotingV2 Gas Rebate Correction Audit - March 2026 Rebate 66 VotingV2 correction + +Generated at: 2026-04-29T14:22:46.795Z +Manifest: `/home/ubuntu/ghq/github.com/UMAprotocol/protocol/packages/affiliates/gas-rebate/corrections/Rebate_66_Correction_Manifest.json` +Manifest SHA-256: `0f9aab31c8cd0c17d8a40b89ad7c4c1319ce6d90b0357bedd612600fd57a5d46` +VotingV2 contract: `0x004395edb43EFca9885CEdad51EC9fAf93Bd34ac` +Custom node URL configured: true + +## Consolidated Top-Up + +- Voters: 585 +- Total: 1095766860809837881 wei (1.095766860809837881 ETH) +- Payout JSON: `/home/ubuntu/ghq/github.com/UMAprotocol/protocol/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json` + +## Audited Rebates + +### Rebate 66 + +- Paid file: `gas-rebate/rebates/Rebate_66.json` +- Block range: 24558868-24781026 +- Paid total: 2072979783179918476 wei (2.072979783179918476 ETH) +- Recomputed total: 3168746643989756357 wei (3.168746643989756357 ETH) +- Positive delta total: 1095766860809837881 wei (1.095766860809837881 ETH) +- Negative delta total: 0 wei (0.0 ETH) +- Positive delta count: 585 +- Negative delta count: 0 +- Event validation passed: true +- Retry count: 0 +- Split count: 0 +- Anomalies: 2860 + +## Expected Delta Checks + +- Rebate 66 0xf20737e48160A87Dc9D1B26D8B63C796d2F1EA91: expected 7088051537280779, actual 7088051537280779, passed true +- Rebate 66 0x2a9437DE0cCD4FD7b7D98831213AcedeFC7a1092: expected 1902006430166225, actual 1902006430166225, passed true + +## Negative Deltas + +- None diff --git a/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json b/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json new file mode 100644 index 0000000000..109476ebd3 --- /dev/null +++ b/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json @@ -0,0 +1,595 @@ +{ + "votingContractAddress": "0x004395edb43EFca9885CEdad51EC9fAf93Bd34ac", + "rebate": 66, + "fromBlock": 24558868, + "toBlock": 24781026, + "countVoters": 585, + "totalRebateAmount": 1.0957668608098379, + "shareholderPayout": { + "0x000000000000f8E4fE2a98574fa81C728e340764": 0.001623200791717199, + "0x0013Fec13D8e4bd86AF7a988087B697ca1057B88": 0.002070984318620129, + "0x0024A67e0b91131d6978e1e0f72c94497bDBCc35": 0.001982718698536916, + "0x005CDb3B0B0964569ce0aCbEF483443296cE704B": 0.002337951423375661, + "0x00B64e31a3C6f59b2120b50b8741584f024722C7": 0.002629035364475586, + "0x00C3C106D11322c7aafECBF248cEE710ae3f0a5B": 0.000597858515100745, + "0x00D71C4FA96e518dD54E459114408e7aF9297C15": 0.002392552700169229, + "0x00dd323d8f4bDcEa52EDBdE935C1ee97C009c5a7": 0.00030078413245808, + "0x00Dd84F50e5699aA9F1a9f4f52c428BB305189be": 0.002254650304625379, + "0x02153ebE18bc66C57E540423E69A881a70823d40": 0.002618388898398077, + "0x04AD0F62A66bf8FfF774676a792E88D10942e2A5": 0.002084882404298553, + "0x05C6A4dA04bE965B659aF1365314bCade309bB82": 0.00124088623202724, + "0x05ef6560a7c9C2951B35AFea0868382487e9B77F": 0.001449839720952172, + "0x06Ce05Db7D0A4539B3eC2fa6b81DFe11a32120eA": 0.00213402154104884, + "0x0724CFd1B40f56B506136D5A89EedDda31deA725": 0.000435114378111624, + "0x074F2CCfB2716fC8B6aC579173f1aAeB1f759d52": 0.002251043091099571, + "0x078352359cBd47652b6aF7dC1c46DA5Ad1378035": 0.002534179075446767, + "0x0788f0420961aE4806fc4Cba0898A9ca0300eFC0": 0.001227657140494814, + "0x07f88CeD359895Ef9CE4b3A09746954e7eDFf139": 0.001343042563385011, + "0x083083Dc8dE34B1dB09910ebC8a8Ff7a47C546ce": 0.002725193807169186, + "0x08610322dfDa1dd2D129b647e13840e832D485e7": 0.000357972841447646, + "0x088887cCa9F1E0a6a4D42BcBD3e107686bda2486": 0.000670860511931726, + "0x0894f897CE9b108cDB97C239e4f96C407a248e92": 0.003149757188583824, + "0x089773A760FEE0F1A3D3ECfADf4b2E145FD1E88f": 0.00169629330901413, + "0x0914Bf3e3DB541a79f6587F83A921Eaa368CAeA3": 0.001110997322694742, + "0x094DB477152D5678A0cE5e263C284DFf1052700a": 0.001250099351514977, + "0x094F5F0706DB7e3715a87Bc37437f2E6e6029B3c": 0.00056259881232371, + "0x099aF188E9c68B91617EfE4b09Ee8CD90ba4c63d": 0.001958173934655549, + "0x09a10823b87Aed0A3c348C0a20d69d3276192913": 0.00106930717885286, + "0x09C1579AAE05524f455AC4852d60C3e973ad0715": 0.00328306669870331, + "0x09cD0D28125587e39a29CF25Ea3f7851C585738f": 0.000532900234024956, + "0x0Ab373B6D140dCF3919E17D277Ad1Cb818B1EA53": 0.000598416251823648, + "0x0b0221d279026aC38eec4e13408BA7966Afb9FEe": 0.001701370489208542, + "0x0CB8dA6C265a90B3CCE8431267c0A94a7f1db875": 0.005838128588386673, + "0x0dD7762E2fe09c9eE2F5aCdeA19C102f7c16D8C2": 0.001237634310364501, + "0x0dFb17299E2b39C63602Ee11BdDf9688Bb66449C": 0.001491818707670364, + "0x0E054B1F4b103A1C92866B3205EcF818334caCf0": 0.000265937422231955, + "0x0f8fe8e8B7Ad38615904a08e821E875fa19d8b67": 0.0039965363551254, + "0x0FaD7Fcb19f3EBe9402BF0623d7ed0FC4F1dEf15": 0.003798075899170629, + "0x0Fb0e2fF6739060A811190b94b6D7da786735be0": 0.001649341817605003, + "0x1098874e7b4435615CAae49AF275B22e195A574f": 0.004958508195265784, + "0x10D6F9Fee0d48E7db7279AE0139cb5b577bB5516": 0.002686585110209063, + "0x114D4348265E8302980e7BA2db441FBF09EC3303": 0.001605566072098302, + "0x126db3213b309A8D554594e591e614425cCaC78e": 0.00210489624540066, + "0x12abC23621Bc6a6217c8190Efc21Bce9e0cad459": 0.002036727767680347, + "0x132DA096d35f9DeA0FD7F348232582DA4e551dA0": 0.001911522861608885, + "0x1379D42CC081790d6205712b79f6E133d798af81": 0.000929662792426936, + "0x15856FdCA72b0429E6E2117b7675dC2b0E6272a7": 0.002142293956414096, + "0x16D12711626310b5894783ca187BdAfe7aa4597A": 0.001347869592891393, + "0x17e2eA46935588BcE435278Dfc4Ffb31F8039BcE": 0.003101468775876044, + "0x18fEe6e511646B8ea2e4964277574F637Bc03f3b": 0.002979943874029252, + "0x1B0848A69E665eEBA88bb877b67145789d3d8b61": 0.00294200765490773, + "0x1bA4b6B2e5864838ed336495eCE7f456b1ba1FBB": 0.000271516145173994, + "0x1Cd79a62361Ff4AE9CFefdc128A255B1495627Cb": 0.001094860335258598, + "0x1CEe194Da1eEfe344fb2e7f46faB7D3A65C078e5": 0.000554433439102433, + "0x1D1C0E8394e6619Bf75C0F2e9321B3D324409283": 0.00234538028077862, + "0x1D463047F4c954D70d2718AdF96c43f24aC19dEe": 0.002720351640606777, + "0x1D98cAEFaB4bb543d98Ec6136E1498c34AF32c85": 0.000905622562308438, + "0x1DE746BB64222C304b38F84613745323cB6C7fC1": 0.007710366790600202, + "0x1E1486d4c30fA85E7fD5AD87cC7DcA15a626374D": 0.001704259387520791, + "0x1EdB50d83f76382480886597A3023fC318B2ca66": 0.000480554189311596, + "0x1f12254be217Cf9E9BE46960c36970390b07f16E": 0.000564319584213034, + "0x1f63E3125AE5b76240954F78dF62b4684CD88c25": 0.001171153912008066, + "0x1FA1C17dc5dAA02730b97B7a9b9D75710244d98e": 0.001403209286460627, + "0x20271eC8650e0990201EC5c785a5f3E8b51850ff": 0.004044210483401355, + "0x203F9674bE9782BC4B194625Ee9dC6800e65B2D8": 0.001117684671989674, + "0x205a89902311Bb2c44668d5712D7a21781279150": 0.001085309373654446, + "0x20A0fAb3e883852228dC2D54f4fCd4ceB6b6cd68": 0.003650632091718417, + "0x2108a6d1f32D1A932431d64E3328D1d45bD0520f": 0.006374040071022786, + "0x212df1ED15FB55607f180b8E26dA4A3db66b04d8": 0.001398354506323405, + "0x21681B5fac7Db2d8DD027487FeA9cd28B5c192A9": 0.00425641869693439, + "0x216bf62B05246bf4a1694061E8769464A6BFD812": 0.000584902357161496, + "0x21a27324B609e864882778c703FFc42Cc05daC40": 0.001894091978422001, + "0x22992D673Bacd1a43508294fc00597158a6B5816": 0.000340594444861752, + "0x22B95B36a3f4a7dC952765f9CC110ab455Ff6E4D": 0.003513543769493914, + "0x2352E748C9C090f44a8418f74457554CCe8D0485": 0.007120473344033869, + "0x239a01C50406Cd2d5943B408b49b32226741E1CB": 0.001367521023877095, + "0x240d2243D90E8968D0c8E807202bC8a2DE0dC53C": 0.000230780779968753, + "0x24eb1c355C05439819a23DD0842D5D038d1CA05A": 0.004296183001431525, + "0x24F16D0Cda8c2De21c762E0295C28d7249a972A4": 0.00309793217410008, + "0x260D417fBD1716B1375CD311f8a6677c4a780B3A": 0.00214937623772284, + "0x26fd27a26a6C1EdE36214512ee4E56440a0cEbF5": 0.000470793957213322, + "0x27064Cc4FE5bd5a20d0e5A21390a45F5a44Bf7D3": 0.010849346915887568, + "0x27459423cc0f816D965A97dCB90fa45774a18C3A": 0.000750370507871038, + "0x27b7A1b3c4A872FB30cF22e8716596a2312CFD2d": 0.001857557792118634, + "0x28cCfB369Fb97929068Cd30A390D37fee0037C61": 0.000573788814505132, + "0x28eC3b46262c614df6D5A3FF2726c9746F1d1675": 0.001541893574210529, + "0x295c5B0C1D5acEa1A94eDcd67005aec356ad1c7E": 0.001808342328838047, + "0x2a9437DE0cCD4FD7b7D98831213AcedeFC7a1092": 0.001902006430166225, + "0x2b379bFb86e900fE8f3A1434ee79097Aa5b883dc": 0.004023124829165172, + "0x2c26767989D49215d249e6D36F8e3FE2717f7DBd": 0.000046626720589143, + "0x2C281042A8dc2699e4e2BcDac11c2810dd40d8Ff": 0.001671269695907393, + "0x2C492138498165C3f6fF94Ab7d0B7Ab6dD546AdA": 0.001042570356273628, + "0x2d14a06687629C8e0F9fcb985814FcFfb60FD36F": 0.002804508864017687, + "0x2D29986ad59F77676c204d09b44Cd8Fc9EE7B6a2": 0.003084938156140876, + "0x2dB601b85292C8c94E87BAc3e56B3fD19CA45063": 0.001955301462889607, + "0x2EA989edfCac6531cd912d09A456f9809BaA5377": 0.001248519426706471, + "0x2EC20e5aA17F736060356f6B186208D5Ce0aB4b4": 0.000401416864313636, + "0x2f55877D6D8A42BD87e0325201cD15d63aBf5866": 0.000522007119886494, + "0x2f8320C2Dc28681Aa5BBF92e79C37BE656a7D5F1": 0.002442970611304262, + "0x2F966072f36109F27539E5EdEfA741912206E491": 0.001030197369633942, + "0x2fbbA6606C7628b749C6814fBAc1f88fEB21aeFd": 0.002728062359897463, + "0x3009e81f3b145c71A409313306Babb0AcC219aDb": 0.001007745932840434, + "0x3081508f0cD453Dc99Bbda26ab35Edcd785cdd88": 0.000535939904748932, + "0x30b2DAEb3757B6C7462cd0D776828F8d7398BE50": 0.002955698206664348, + "0x314FDb3cE492ee03a0eb037De01Ef53757C73936": 0.000773119450595252, + "0x31C44F5af149d2C9374f6A4d7253d0Fd69b127C9": 0.001039654649858049, + "0x32006a2557954336E877Db126A25e4ac27897C86": 0.002001533622567478, + "0x32a27a34B002aDE54C21515f77593E2086f5E7d0": 0.001904149153193711, + "0x336701baB9Ee6a829a5d610A301E978ACed202C4": 0.00105201937374925, + "0x336B9DE28D67D692C31DF93A9b8630B2Fa50d88f": 0.002417887862933094, + "0x33dfc8Dc28853A4f9FC0ec04BB2B67C6379CcA7f": 0.000609674711855852, + "0x340B8E5B52619c0ade021F806348e11274783740": 0.001392412572417687, + "0x342F40FC637e631f669a5b38fA4fc94Dcdd7DBED": 0.001285220148936264, + "0x345B46fCF8E503AE3b89174a59C04D2D212A5a10": 0.001982372603469258, + "0x35A7f9DB799649908688826E06CA754Ea0153724": 0.004068294499964118, + "0x36Ba943373FdE856457511ef8E8955323174331c": 0.001304975240793567, + "0x36Ce63c738971B948Cf0Afb842b7617254C15BC0": 0.004321177405122993, + "0x379570ffA1A60790A8B5955cf643F868D6ad4c9E": 0.000531220997599391, + "0x37b9171eF596Ac6A57c1d2598D71345e2206A5E3": 0.001944819017097703, + "0x3800Ebf79fE712781916EDBeDb169bA295dce5fc": 0.00080065779667571, + "0x3895799b03759423C728Eed3aa0C0414F5179f79": 0.00103015959453971, + "0x38F855e64542641f9e254f6e527351b55b560C0e": 0.000707484196836413, + "0x393950505b160607F40D11AB956C9406DBe6e4ce": 0.001439077395382837, + "0x39ad454BAD7d4909137cDAF1193cC847eFA959AC": 0.000998226306326582, + "0x3A4a969169aEbAb4e9AC667C9aAC62DC54c53A1b": 0.001661521763325315, + "0x3AbEBE2bFd423dbb6357674476D44E9bD178817d": 0.002273991452265629, + "0x3b59d6B33E8F8dDF9734917a40056D07548a4444": 0.001128045778703466, + "0x3B7236C911F87fD75315c4Ed44A1D2EEd725Ad14": 0.004678752876715251, + "0x3b84E3FFBe845c0349E258f243B5F00cA22Ba587": 0.000404368233109516, + "0x3b9fFD4CeFFd768DF16d79e7492A1BFfD087C44f": 0.001969189304064087, + "0x3bcD8de636cEa72178D8f1285f5Af0dd02d0B142": 0.001867467103399945, + "0x3Bd0cbC96186Cc3eafB304111e6Ad20a4Ac92F8E": 0.000431880615588246, + "0x3c56D7BB7b81282a369920F4816D75eFfc549b33": 0.000212558777040274, + "0x3D65eD138686e2AD54006d4Db83aD4597D645370": 0.004183334831553569, + "0x3Dc3862Ba073D508e421671c7F44e9Ee5d6B33CE": 0.001686882027902168, + "0x3e1B1A4a8fbA26E80F4678d3eA3AC1DAcA78523e": 0.003125073719379432, + "0x3E59864442ff8e0043b5360Cb134F6Ca2d514152": 0.001862838207470264, + "0x3F180F32AeD8C10Ce46065e05185Abc69F1D70B8": 0.003428894356078606, + "0x3FB7d3E1212cee588b14E57aE9A50eD93eCa0580": 0.001483608671467378, + "0x4010650464cc07e447ae10d3135F8c82554b2528": 0.000534635647165048, + "0x402bED71F1B26a068664C12818ed721E37155A44": 0.001992875732155986, + "0x40602DCAfbeBb5635ede96B2EcB94d534fcB4670": 0.001130821318515792, + "0x40bFe49745Df251fA0Ac7a3f983101FF170c389b": 0.000451794451432436, + "0x40fE8993df6f3915540aCE94E3a3d86a48829664": 0.000563271918036863, + "0x410fCF90a3805DFba3939827b0E75bD5fc2ef8B3": 0.003074690002145242, + "0x415106767827A7856D826458a486a87e0e15097C": 0.000452424928595454, + "0x419d955a9C3dF6A1b9eB3EbF2d21a3C63A8d57ef": 0.00400654081690959, + "0x41a1F47F710841F2f4cf492149C205725875f400": 0.002325962715286745, + "0x41DeB171107fBdBb7290eB4a8E77142c4636C13A": 0.001894591765754071, + "0x422Db8FD3778343B595762417b62474919eFeD41": 0.0019755448305781, + "0x4241A9998720cacB5902cF887A5323Bb316E3166": 0.0008062558287423, + "0x4241b7A1b190F97213cc092237833305af62f563": 0.001076317288004069, + "0x4289C656B76B20eBF1B5Fa4363dA812346919bdC": 0.001136506580316892, + "0x42a786c945032Dd0AFaa89fECB659789b56B3FfC": 0.001902747861644057, + "0x43E6887aFcF79DbB6aD9c0B22f802B77fd7c6404": 0.001950850611772753, + "0x4442dD25DA06786c78d8874fB33381E706877FeB": 0.002045392642312193, + "0x44C642f69a39F1b2b788C013c3839277cBb24DF5": 0.001983616606745826, + "0x454fd6d5FFe4780577ce64e7B17B39BD80158021": 0.002200839051644971, + "0x461980B8560EAC362aE5E685cB5a35952714611B": 0.000992761419614184, + "0x463bECEc49d10Dc785110031B9F6AfFbb84b6aAE": 0.001304490755382015, + "0x467c3C9D910fF352c7472571d3360bcE53c2F6B9": 0.002817229027824432, + "0x468876cB9b5850359609Bb4Ec7977a3f41AfdF75": 0.001203599383669484, + "0x46Dd430cD21e39ef9A06b40406BEeF25B3810210": 0.003142803920990852, + "0x47A40A367b3298BE3da3BdE3994c5342e26f368b": 0.002574440801490452, + "0x484637541D68ec3627Ae6E2bD7192E167b88E93C": 0.002889776300040188, + "0x48767f20ec0aCA7f47b3dA2Cc32Bc06549470A9B": 0.000519569925810646, + "0x48A384D082C97f82ABDaC55e43EE8f2392b9f394": 0.004047524464547004, + "0x48c7e0db3DAd3FE4Eb0513b86fe5C38ebB4E0F91": 0.0001090248, + "0x48d26F8F052d80E943694360899C4bB83344FdBC": 0.001719069438432509, + "0x49135912edB24205E1b0E7b9eA71887edC59D50a": 0.000421542883416198, + "0x496A936f46dFaa912F128CABFA01BA6F56a520c6": 0.001115920301574156, + "0x496cdac4854423c66EB0Da89f9e96Ef9D8312ef8": 0.000876634598008012, + "0x49b3fB1B5E6C6Ae2A0F15dE68F73F9e5Cf99Bd78": 0.000165806687619094, + "0x49BA7fC7a31b6d49e0C7eDcFF76C1678078EC8F2": 0.00030506313509658, + "0x4a194280157860E8aBfB7446Cf9eE84bf66dC839": 0.001650531881154534, + "0x4A2e4FD85Dfe564C5b14A134AcdFcD531a5BdB92": 0.0003379454536506, + "0x4A6115D5ee87a3Db90b47881B7d6e29802DEe62c": 0.003829541985395866, + "0x4AF5B23Cf8B2EE85Ca974DA6a51fE12bF726Ae6b": 0.000477202257309814, + "0x4AF80E6414EfeD0B91FA19c0D19B46C381beCB7c": 0.001131272892735052, + "0x4B8aef878255F6242606Fe5e73D659004F5A34fA": 0.001585130521359351, + "0x4C7D5a6437B325A998f83d9dcC267c5fdfF8ef56": 0.000772818599011801, + "0x4C9B462e44B14df09912D99Ca7a0daf9fF0d6f77": 0.001411727440103071, + "0x4CD6ac17782D95DC7a8eE2106fF8de4a52984B01": 0.000235348811664286, + "0x4cFE0198958D72546c4F8E415616B4594DF18679": 0.002801481749290462, + "0x4D2141b31437E970A0f13c935180194a8C4308C1": 0.00205394078474958, + "0x4d237f8E3364Ac5104765d287cDDFbD52b3C621f": 0.000257312493278815, + "0x4Dfe8442Ad63763E7D143BBB40F6A9A76F86a551": 0.001378504412637978, + "0x4Ed43703F882CcAC37897Cd46c80e0462be5C91B": 0.001671144164619649, + "0x4f49D938c3Ad2437c52eb314F9bD7Bdb7FA58Da9": 0.002205644371239276, + "0x5002a9263908CAb85BB4c71559227647F82530e8": 0.002916957364213548, + "0x50229CB8317ECF297E65cdDBCe88e0814eecdf9E": 0.002130687755108406, + "0x5060020e66031c324f77ae24F14Cfcea6A688Cb7": 0.000436805264451654, + "0x5071e6d385f584B5875166563c1670460905ad7B": 0.003897061222411612, + "0x50d26FCb38a279043bA075B86df912Cd523931Ef": 0.00099617178833104, + "0x517E758fb4095a1D250D084eAF16DDd041577A05": 0.000418521973844092, + "0x52A11a19528DE46078fe1118aD45540A5ee514bd": 0.001302019002861303, + "0x52b88b1f9e4B0E8B3738c2f4AD0EcA5B73ab31F9": 0.0024326559705695, + "0x533758cC4EDF0568E51e322367A9Ec6fbE24E9E7": 0.001557848461192187, + "0x5381B78AB971afD2ecd44F1431D635541aca696f": 0.003438903181023736, + "0x53A30736a43c413Edf5C13F049D34d3Dd57B7128": 0.006332039302005524, + "0x54B74D49cbfb92343E4607F260BE721b208b4dfB": 0.000362656876207634, + "0x54d6390e19Ce818209bD3B53a5d0D2E0c6FaAe04": 0.001099071979430954, + "0x553E206F3F504c3E02258cdB93614e0115827D1d": 0.000995348388598626, + "0x5576023B904E1EBE5c35c7C041bbb2806e890163": 0.001551113132212002, + "0x55AabbfA2e5D574F24aF480E181355DC788E0Cc6": 0.001550301160922042, + "0x56719d9844bb7968941fe7942462Fc38D7448896": 0.000351628609946178, + "0x574c891acEdddeB18d112DcE69F87241794307c7": 0.001001537126390391, + "0x574Ce8Eb2f3BDC44Beb64eAA9e629004276586d7": 0.001841006912831389, + "0x579fFc05d22484336b803DE2201Ace27A5Ef5e0d": 0.000683903625555655, + "0x57b92dfC53d2D50135946b74C02f0E8c472A2f11": 0.003034112585321238, + "0x57c106cD365B436aC4a2Feb8690CC29FB32E8773": 0.000558955922466647, + "0x57fDd988547aEFA02dDaAE980AAfF0B031924D3E": 0.001241214821572192, + "0x5836Df3DaA6E9B97434F77272a3e8ae3c478D0E7": 0.004138713207712326, + "0x58504a178E3A3B8B65E51a9014679550f1dC5a86": 0.001830886196590977, + "0x58706B388caA1D46091F1FE4559F6BC77402B44C": 0.002665148578325707, + "0x587Cf3Ea6bdDB04A5C6912AC95120443f4474115": 0.002277413218547596, + "0x58CFC8ee2132847AfcDc67CdeFA92b2D21eB5Ba9": 0.000984847744131868, + "0x590a8DaE6861CDc2b0300096ec6E4dc6cF2143F6": 0.000405833426453988, + "0x59760d82C6c5B6B6F8865093820B74B5325d775f": 0.002091237757157023, + "0x5A7c9e40Dd0b4173d368c3A810E5fef2E92F73a4": 0.000555494147591108, + "0x5b01ce79D8b3B793DA3Be5e27de3A767f1a02eD2": 0.004090213034835558, + "0x5Bb7e188594870CE0296CC083aC74C35B2565709": 0.001189219689035914, + "0x5BC3D8339754B5D4455355B3C5CF2639fB943942": 0.001058707797710202, + "0x5c4907bF26883c8dB9cd38F314bB4DFf710593aC": 0.002828673988841977, + "0x5d2150E5d88A30d5793c6C49959B8f7d350a36A5": 0.00062317021023243, + "0x5DB732749c6871540f481c15eBF353fC03c225D3": 0.001579445299430718, + "0x5dC0A2903554A228D9331ee0748F1A712d1E6d39": 0.006863964665223741, + "0x5e4180eADCD9328c0dbFBDAFcFfa73c8eF831Ffa": 0.001782939204355069, + "0x5eb31519474Aa90E492168a403Fc2AB4522ADc7b": 0.00143006919015883, + "0x5EBC1D2809f4DfcA9Cb518EFd2307fDFFC36D55d": 0.004396707672251835, + "0x60307A482765634C9fdb773fCF4066bf8614df8B": 0.001786812667424917, + "0x60CACe9B90E3A1E6e49b1EB16BdA5fA631cf23A4": 0.001752650545741213, + "0x60e0D8fef5d86615067dD713cA3ecCB2dC669993": 0.003183531176946441, + "0x610C6f79839DDA54E8a587e279E6e93a0BF589c8": 0.002039304527156259, + "0x6137A7c745CE7ed7a6eC8cA4AA5B635fF17d5467": 0.001118648746654506, + "0x6147d56b02faBD35cd9fC2B80a60276cDf089521": 0.007326360624243218, + "0x614C52345D9a2542460a765B7332016BA73599e2": 0.001361811851143692, + "0x6209e6ABfEE4Acb6Cb6C2d5FF8CAA35CD9B87984": 0.002448488320059453, + "0x62A1Ac16f4Bc32Ea0B65795031E75419a46F8F01": 0.0040086091843321, + "0x62a3e17519aBCE8b5B12A92f3E01bB6b5CB09751": 0.00192670093424056, + "0x630A63523A4f079201fb548114695d8da1d742F5": 0.00044897364183439, + "0x636223B012C4d186153CDDd584F3f4F733257Df9": 0.000939801620133649, + "0x64125D5e793b05F0290e4d322a5b05Fdd3EC2674": 0.001317701293673964, + "0x64230Ae13E943e41450061d01f38b606E6dc996F": 0.002025486495699609, + "0x64dbcD6e381a4833049cAFB83eb6f441349B2F48": 0.001279016189798426, + "0x64F86C703002b9fB260C2fC65C15ca0e65530fd1": 0.00176381571977205, + "0x6573e30Ee0ad46BC9aFA0C2aDb0D3f147D658EFE": 0.003157830075647647, + "0x65DFdAec30d18F98791153A92F1f4cbf64839Da5": 0.001171524258265209, + "0x668D123f7AaB549301D9444E582Ee4ccd379C4f9": 0.000256239437651421, + "0x66A93EA89C257a03a125188f8eB742972537bA85": 0.00289610883123106, + "0x670aC9fE190AB0Ac2D6829eE414F221794B22cDB": 0.000367961554486094, + "0x6748445D83259a6709e459873323324a54072d1B": 0.0004125245335512, + "0x677350145860d4937CC04bbD29333C321862Cd19": 0.001810100757137645, + "0x67b4329df2274F21429538a1Cd35bF604C35dB59": 0.000617427740993167, + "0x686c4D2ce918805D05FD93F109e279b0c3DC8Bfd": 0.002697900891135362, + "0x68Ba3e38585941E2aBEc12e18c6AC11E15052292": 0.00120725538056029, + "0x6990d1288EF65F0d0AD9E2c54d1ABc91118C64ee": 0.001512452283223035, + "0x69D0341d380a1229f4751a0A721345dBc716586C": 0.005333525067475858, + "0x6aEdb6460ABAE82F5ED77aF1d5e9Fe6F701d8c4A": 0.000887279887748914, + "0x6B56fAecE16358B3e63b231837963465cB98A152": 0.001459143800064487, + "0x6B7d0041B1B05f1D8f86AE923Ec09557e32Aa416": 0.003073934112787674, + "0x6B8F4dC1D7D243a9f9b506D58020c866EB199885": 0.003176410682534911, + "0x6Bdb3A8ae008cE1d3073870c852010E089FE6753": 0.001872626148991244, + "0x6C9b8Ba06E2212D29561A5910f418a042fC788ac": 0.000273335624404536, + "0x6DeB5c18F9d75d5D8128F8F42cEB225dD234F960": 0.001627868877751568, + "0x6E99c76778B44b430d5dAc1559e7AA9DD76dDac3": 0.002352943406227767, + "0x6fDc3F38B32fF607199B7ba12459D741CA6f4357": 0.00251976638956371, + "0x6FeC2026e8E468825ED243445508f1bD1215059c": 0.001926101782739981, + "0x709e49864C46A307e8f383c6B0094062b74c6765": 0.000832106669875826, + "0x70a7EACE9F44F3C27832f92Cf5EFF9B7ee3Ed2D4": 0.00033741151530551, + "0x72CAb6D1Ee9676DA8956A7A8E74EcA4052d19696": 0.003437454405732068, + "0x72e1260FFa7e3e7F41eff646B24694F8c139c73d": 0.002110320098252279, + "0x73714FE3e21C09FaE810380c15C64b5628E5d904": 0.000498372346319018, + "0x73A5db333D383155D2E4fC506c2802B557108E51": 0.000230977753115089, + "0x73cDE0e4F0480EA6B98Bfa292Ea936685716af4D": 0.004182221756493842, + "0x73fcB73D180D013ae1dbE306DFcD59C5Ff01b66a": 0.000333931769184205, + "0x744c2f5FadbC305d20Fc91274b71a6896d294946": 0.002154405987584555, + "0x7460B763e92f58f58B80F6650B41F3d2cD10fC3a": 0.002068248961183268, + "0x74C9DCb37E9eFb795d4696212E8ae4c68C4d3D1D": 0.001223240999749143, + "0x75F223915302B9bA12eD8F5425f88b74379bE6aD": 0.001110282436521396, + "0x75F5607Fe0A27c57CCd7B1eD244Eee9499D68302": 0.000853395997600356, + "0x7643d5cA36aec928C15181F02A4263D9E1FF594B": 0.002011786909719163, + "0x7645e40EF215f9Bc44F384a0418c87024646e489": 0.002044342586676759, + "0x765C6299ead6a2fa713E0D323Ac6BDc96bEF214E": 0.0033278527113547, + "0x76bd993BD4A08FE154690095Ec0a3DBb51a0eb08": 0.004076238444491684, + "0x76cC155EEE2e97A34AC53e8b89fc44690Da753a0": 0.00240577975892889, + "0x76cc3f2Fb3f451BbEeD11bF9F64Bb35f43438829": 0.001990813064873342, + "0x76e0eEF2E4883f5163ACabBf1C00a8eb73D25d83": 0.004764401388187936, + "0x773B42430376334c327831C1AaB73f44A379F58f": 0.00038044383161311, + "0x78044a54e9009eEE6aba5A9418EA6380f153a7c5": 0.001874776999470425, + "0x78be141970C8378Ff7E14dc0E817Cb17b342F5e4": 0.000409374561948349, + "0x78d964e9629fD6104F8F13d0DEC2485Bc1a43A2d": 0.00120915164941758, + "0x792ed5735E87859792f96bE92E98360fd7c76084": 0.00056833064235356, + "0x7975ae9ACd918f2c2F77a365e9077d098A102C86": 0.001818905533266983, + "0x79c8039C0cfBDC3cdF8d66eFB1AD2836E698ea3c": 0.002745207218955531, + "0x79F7f0B17404756c405be60A60A491058C627958": 0.007808654191542071, + "0x7A75B62e21C490fe9a27A50a083D6a2b04c7fbbf": 0.00054190741796834, + "0x7ab3c28958844A758FFA564F09c73dDa7Ffc766d": 0.003062750855771312, + "0x7b56128FAB23816D4a7520Ef691e2607af97B01c": 0.00087502027835499, + "0x7BAa3b328603535006d76D7B80aF7260FD8A946a": 0.000450916094931589, + "0x7c05dE20A59b43c0Fe27eA1B85A2872E9EA519dE": 0.000297367085888908, + "0x7c9c7bB3D6880F0d720fEb4fA6164Bd3E49F76ED": 0.003325422172311954, + "0x7cA4b00a3aEc07F978D127E69bC16484a038619C": 0.00045013115069857, + "0x7ceb2a5C3395A5cfE09B66E7cEd496061301c316": 0.002232276676490786, + "0x7d822dd2320B0B079db5DFB0b87D63A0E9F090d4": 0.002860405156906349, + "0x7d8AEE804Bbad88d0081115Adc917F5d9bF6388C": 0.001899743234221034, + "0x7E1B249e6BAA2F60A87B14b43B1Ad731542bD9fF": 0.000700318590733549, + "0x7FafB471bad0589FaBa53769DD8d76c5d79aB720": 0.002629024243659779, + "0x80040d9c574156125E096d85AF6B6c86668d6CDF": 0.002222021358202793, + "0x803E38C54240244046545B421FfFE4e05BCD5D0B": 0.000403060462062888, + "0x81502de049CE028C2A91e9c91d059Ab8Da8Bf469": 0.005036699466795216, + "0x816a7FdeAA4B1Fd5CaCdD337d0A815347a5E714a": 0.001813361626403986, + "0x81864365b031c138Cb6a7c64526C7357fE4FFA2D": 0.001529874518478847, + "0x81B73F850A76D405bdd976Db6744D85c65fe9330": 0.003353245962229773, + "0x82074547555355BbE037e0E504d0D0C08EC4dBEA": 0.000563930998939954, + "0x83CDb49eBa3bC99AE57F5abE9c6cE9D601Ea744A": 0.0012501767793338, + "0x83f7321a05876f0bF973bEc3033858bb0b91e37f": 0.000253576097907972, + "0x841499f8F5F869c20886D581641DC181E9C6B672": 0.001789989869958947, + "0x84252729ed32fA0fa1b454b8f58B71758239d627": 0.002068626974566218, + "0x850BF360D7062257203854cEFc9A1629106d7a61": 0.000233865148295339, + "0x853E5f1A139FdEa47273A4632c70368d095070Cf": 0.001471304823364316, + "0x8578ffA6a6E9908B454CD38B93D3F11Ca8723A9A": 0.001898155682365782, + "0x8594E5a6f67cB13CF525EA15f2e1FaC3EeF63304": 0.002427596232541171, + "0x86CC5e1e8fb20102Fa7A0fa4afeAf1Cbe1BE273D": 0.000679366196250462, + "0x88330D5c152A3A064b8883ddE2A8a2aa3e4680fb": 0.004364686106772601, + "0x883Bb7134b7f5673b08fb8d3c31814B55bec3a43": 0.001391344852681121, + "0x8891E7796d54cF5b801F0A01966be79d7cC2a89A": 0.00231702783426477, + "0x8903349C5B3205Ceb9D004A051DB554f70D1Fc62": 0.002017975534804761, + "0x8a74781B294238d74f86B0cDfD4eE7b1dBE55d7D": 0.003417530192247443, + "0x8b1728Bb25502476d16CdCF0861669f68c91A9d4": 0.001247214210686356, + "0x8b992B29e691058a1EDD32378dc11E6480E0eE24": 0.001827176639363206, + "0x8bd7B5E860998607715Da42944cc9DE3486A3Ae2": 0.000699346289814744, + "0x8BE6B927c4F3aa56D9c0DCf1be363b0081Fe0BD4": 0.000376122121756596, + "0x8Cd66785F2A1B5ADc3Cc81177D485A8395Fce2f2": 0.000656200320462028, + "0x8Cf35646c42DA86292aBDCf64bd0f7e7fC644a1c": 0.001451440145564425, + "0x8Cf75F1D6974DB5215d81FBec287Ea8EEF35C95b": 0.000519927519621719, + "0x8d3450C45C789Cbb6E03baF1f939B8081ea41Ccd": 0.0018214506906328, + "0x8d47CD9B8b015B0F3865e8eE0b96b8125bb1F483": 0.002040355617210643, + "0x8dB0696b0835031ee2166F130d90Fd31EfacA4E3": 0.002653146287240826, + "0x8DE1cdCF6D3aCC777d08e2359Cd4D6Bc72e382a7": 0.000438739746115682, + "0x8E561b9823d9BF7067F5F64980aE26b6b9969e77": 0.003646453781237505, + "0x8F559d9F555131932345C2A9546df023c54E096F": 0.00098866912405153, + "0x90483C0d08A16058aB7Ec4455B8Be51a30Cc5043": 0.000588149937616228, + "0x90942873BEC9aA28a4957c1FF1C41fb3B8cf6a74": 0.00036617205785523, + "0x90b979c9E90EC5D5246dAE6BE32ACC451edD2464": 0.002100757033999859, + "0x90bd7028416753B38714F32acdE927aCBFD7D18B": 0.001889818145671654, + "0x910144b369ed067F8a2ea470ebCC2Fdb31c0dd9F": 0.002797157336750915, + "0x9247154eB39429505f75096d5A6be52acE076A81": 0.00135806585325456, + "0x929cB3CDB2C23fA479D72c21731C53822f5df881": 0.001448912903002483, + "0x92A5D7978E46759EDbAeF30012E4c60C8DEeE0A7": 0.0010956087692927, + "0x9301580990202CA724E2d2d3F2Cde88fF50735c1": 0.001684434109070633, + "0x935eFc16A75a6f0B59fa91CcD21Af633A117f97F": 0.00370337099812257, + "0x94478F8B27CeDD6177E238F48164A45245C854C1": 0.001102472607435183, + "0x94667C16eF36c34d6De71FfCE6E80C5d24672a41": 0.003389708729565961, + "0x948F052C6Ecb37aBf9f81b87c620Bb272E422155": 0.001326655632232697, + "0x94d0f3A10f88A63fcE0F2304ed63D3d166fdB313": 0.0020490265361758, + "0x95aFE39b111176629BA6eE5F2C1c86eF973226FC": 0.001674189479987855, + "0x967bE9835Ca02EDf7A8c7dfE26519763c1611277": 0.001796203191079962, + "0x96c00fDDa3f3129A55C0Bc9b48Ef504C3D5594e4": 0.00299180331265087, + "0x981387F73e94a173F9eE05a7906E299F99E23114": 0.004312837409283606, + "0x9860D7309039b9A44B1df878Ed4484133a881316": 0.002384094674163708, + "0x98EA9cC7128004b6b09D0fF7F922cCF51D6869CE": 0.000265932280527395, + "0x999EA3182C60ae6F58817C77Da6A769f6f731f34": 0.002049352587514968, + "0x99BcEa6bB0403927fB3c038163478D5b42082Fd9": 0.000874116431832116, + "0x9a0705ab1Cb8C5139171911cF0a689DA2F54830d": 0.000595677795656707, + "0x9a4773EeEE73e34e1EE0E9A64E4b7453b0b04246": 0.004769169014342945, + "0x9A4B6F0839637769e14DdFC03D4E7c537d8e25Bf": 0.002862973385887932, + "0x9b5d6a05E969f58438780d775C0037884526877f": 0.003168447002507213, + "0x9BC114CbDf47021f15416e720bC71b5341120E87": 0.000522280134489487, + "0x9Be6FcbF8d76201559627BaA8B0cD60cE7e06b0b": 0.001762480396329596, + "0x9c0bCC942E775cdff33c64906561A3d75d9D0B79": 0.000125010267582388, + "0x9C9A11a94f95cd31c06E0252eD0cE908b90FBc0C": 0.000317605393089572, + "0x9cDf01F751864333515c209B733501FA5bB14143": 0.001121291953792428, + "0x9CF0Ea03C7e23f2C466d48f6BfA14A85EF7CF4c8": 0.00054107608076499, + "0x9D3a7C178E38748a3a53BE600C922aD5fC45C0bf": 0.003126544705690538, + "0x9EFA7B040eDEC79662F0a7bacddE8bd1db50a8C5": 0.003506710586183753, + "0x9F9a6867d9Ed4630DAC6d3F9C125248600DF03BE": 0.001617015067675783, + "0x9fDB970aEF60007FeE4EA132B5f4EBc376740aEa": 0.003869483672880516, + "0xa02B48ce476ADe8A3f635857dCaF9475F79AD6EB": 0.001616189840039979, + "0xa1df756B063A867bfB3cf1fa611592Aa646bF4A8": 0.000705177083941647, + "0xa21cC0DE85E8c75bB10519872Dd3965ceC351e3A": 0.001173703038582787, + "0xa2E5Dbd496e25A194a11FC3e4Ad5AdA199e827F4": 0.000190120981281462, + "0xa31c2232842e631cCb2d2E4110B356Bab21E6020": 0.001806977094637775, + "0xA33c3B5Bd387B26F72E1c5e76bc1bb81e7935EE7": 0.002904722801428504, + "0xa33f0D43b87dDD418C029412b6dFcFA8a9C68074": 0.00034981925850061, + "0xA3625b1dCB1e99dCC1B9BEB6ceD0965FAF4e20e5": 0.00027416594484952, + "0xa3638f8044d928b42dD74085284bED980b0e0278": 0.001489714764094299, + "0xa3651cadfc97186D5B93A0aD7Ea32C126a794BFF": 0.002467720955045497, + "0xa394d3bD4416380cC3498af7d764fe1Cf76A69C2": 0.001963537059139433, + "0xa3C18bAe51Dfd07FA152492d685c457D0fEE09D7": 0.002029954724613294, + "0xA40ee0717533dE5b87D6f2054AEE815B8461126a": 0.001482451760135974, + "0xA432B3e56A6F4dA4574cDF2f27bea9bbb5543011": 0.000741758386152588, + "0xA4635d0D583F6A5335Aa3CE39CA7D7c2e7a7D01C": 0.001081951101240274, + "0xa4bA32A41A317b970c4ADFE1e1573930c2B4551F": 0.001101759684429442, + "0xa4c8e8D8983e53381b25967659A368f8E108aca2": 0.001392081305519205, + "0xa5D2817A0d9547af625942E6F3a3bEF71E5f5Dae": 0.002463406117634708, + "0xA65EE589b0353e7cd63c03FD534bEa61C748c3c6": 0.003122326719810565, + "0xA6A162FA210411Ef494feAAD1605c415f8fe0da6": 0.002876036318224835, + "0xa7A56D141C552cfB45b4AF6aBFF0aB76f9369c28": 0.00287960685857875, + "0xA7e781E2EA7740177d9b9E13Dd2134A103f5833b": 0.001707803355211447, + "0xa85160a81da205AE57F6d55F16C9C43d773c7438": 0.000328418143729698, + "0xA89fFd4063866481f3DA231bc2cCf88Def15b642": 0.002201741825983557, + "0xa8AD81A7f78a55E02f6267F2568e96445fa2A469": 0.002754570288532948, + "0xa8B8f0B17Ed13a3663A8E3f169C42464aDddB984": 0.002547112551875254, + "0xA8E20D1B16c2821c2E17A58eB9c92c2ec7699283": 0.001759062914952147, + "0xA941ADc6DC04b0cfd17Ffa75329B680C9A1B3eEF": 0.001822412558997712, + "0xaA8eacF97AF9Bf3eB4cBB76E975a5D6aaA220606": 0.000364739785325574, + "0xAAfA1bF92688084C3446fDC741c1453379cD72df": 0.001078139579160549, + "0xaB0Ea94509caa5703362EAaFd8087d205f97a340": 0.001233541625572076, + "0xabe5B6e8a4e79e7F27DB3a6d9E6A6f05e521f604": 0.002119653671187518, + "0xac2c2C3fd735c5DB2aB77D8358DaeE705932ff3C": 0.001378735155214537, + "0xaC880a2568c6F5719AD59C8Ea3BC11a910775757": 0.003592688241339687, + "0xaCB4FA704c4A7092B3373D5c57443ed3261fDD18": 0.003630255800827459, + "0xaD82CC9A78F2cf917E56e6305A01424b9107EC43": 0.000907934643521791, + "0xaDE8502eC7a7Cfe5fc273cE3B94736BB1F76118A": 0.003916966524232559, + "0xadEF6E3234cA45D5bc3C2bdDD4bF427862c60335": 0.00102697588125076, + "0xaEd91598B3ad7e4b6Edc0fC2a0D9E16e8D58981b": 0.002529784784036854, + "0xAEf6a3580A365c524A5bC9aabeB2a13c2A1a7B7c": 0.00436429371858028, + "0xaF4C815CF13Bc8671a2a12BdE62aABEC24651ccC": 0.007448462468293356, + "0xaFD255f71cEBa0c0EceE10fa52F3e2fbeCcE95C4": 0.002017913554351507, + "0xb020747D162105158f31bB6Fc0B6DfAa66B23EE9": 0.003081457554423888, + "0xb187ba422872C0467390155826e5290Fcc9fa3Df": 0.000669892488329972, + "0xB21bE96Dc75717272402eF97A5CC144544263E3c": 0.007989764775625071, + "0xb2a275B464EdcF73c70EfdA20a5Ba5f742470D4e": 0.00080688572111893, + "0xb36268588ED030B4d8FbB22a0B4ECbad1194e683": 0.003581681129386093, + "0xb397dEe549E3FDF24C82b72707cb6FcD849d214f": 0.001127914464566378, + "0xB3983fd5997711935dC61118e684DDCA1CE3F8C7": 0.000298691331723346, + "0xb4C907afdA8C362B58281B5c43A2e7b79f089D09": 0.00043259757817898, + "0xB538544c0d0971dc6cdcc17a1Ac50A02bc0A8B0F": 0.001446947123780433, + "0xb67a6E67072025C1db86e552dc17f7Bf9C296122": 0.003520536193415728, + "0xB6e74e6fD559f9207679D128ddDBb35B9042A166": 0.001782015073476024, + "0xB73812cCE6F5cB7ada40A134b4b16AefbDbB9472": 0.000335504749350614, + "0xB87000FF076e59EBBfD973008Dd21941Ff9D13b1": 0.004408962239023198, + "0xb87087bE41D0299e31ee8c274540a8bf15bdc1DC": 0.002544955155700901, + "0xB8B5caDA2A1Ab13f421870555F99887e3d6A2e77": 0.001861507909183529, + "0xB8C8D5Ca07C82e7E4c73f0cE93E2a7dD08956cb2": 0.000566355500311814, + "0xb916A83cC28F6f63ca9807AD3bFa84d9e14DF963": 0.002088068889187287, + "0xb93EFD0e79b769D2b3Df7aa64d89F983D2fd02FC": 0.000337327081910856, + "0xB9F187188A9cBF21b204F125Dc116a997fC29aE9": 0.000270307464448756, + "0xBA93f72e240d7F45DB22EbF126c2D87dDE238918": 0.000760381014311528, + "0xBB323229972D001bbF725b3fB3734eE53B7455CC": 0.00041913220343746, + "0xbB6aDdBC9C95100792Fd80FEE1cfB46881DE84b7": 0.001306095906016642, + "0xbc45a7315eda040A0e0a53E022b62042a71077D4": 0.000287544605221634, + "0xBC46980A01D8301D336fbf9377aAe711d34fF122": 0.001833265197573606, + "0xBE71d84a622010A0C9709a443017FA53419706f5": 0.002003770387416666, + "0xBe815fD2CBF30D07b804d643FbEEd27b8E663acB": 0.001385352508463922, + "0xbe8bD46D8847a8319261F6Fa137156671dF68982": 0.000230976636674221, + "0xbf72eE28dc8627AD3e76bdA841247EB39837806F": 0.001899623293470812, + "0xBFBcD879dd913255B32100a72A581C963e7b0ADC": 0.000299029647509498, + "0xC0867A1D3deAd93c0E79Ea3fD54422671BaAbF37": 0.000256529672672097, + "0xC0AAbA6E0dD2Ca4C2BE7Df446C121C3E6118bdD2": 0.000930044726786784, + "0xC0Afc9BaEcE062D4cDbbb56eFBe33BBd827e560d": 0.00129605226073346, + "0xc0c13E73641080b8a890261b731f9872cD0bC9d4": 0.000117110196735569, + "0xc0Dc4010e76fbD53C82b19f8f8d7604e37289fB4": 0.0005085470286171, + "0xc0FdAbeF949f28332f596e66eE8e06a13A103c02": 0.002197195124105275, + "0xC3Ac3355B2686Fa503246a92e34D0B7261b39d6B": 0.004108176013136093, + "0xC41A3d9ED9DD925fB057b7C1599249CDB4C6B66b": 0.001776535432640127, + "0xc42851d834037cA1f82668596233DcA69654867C": 0.000558941540925206, + "0xc477F54B5ABBc255f366aC54FD924a896da5e6a3": 0.001327406402168072, + "0xC4E70E97A54bbf4f9796099282fA47397da4b4D9": 0.000665931259830168, + "0xc56d5742F3DcfB9Ee9aCBf8d86385B61b1F0bB33": 0.000733689799816614, + "0xC573dDc59824F248D3688DF0474805F35C2C09c1": 0.003429880143140206, + "0xC590314dE55b52C96eb34eDbC4b55cf8Fc8cD510": 0.000468622920904, + "0xC5b1624c0aFad0E366A9cDF80C08C3ff8253710e": 0.000716488718332234, + "0xC5c90045A5D097625634C7d4bb7dBfBb8E3310AB": 0.002151916154445083, + "0xC5E789964681a9ACf7D8C84EE89252Ad531E6C8C": 0.00209505471583887, + "0xC636DA66cfa5c363C4785835069dcAF85ab91feB": 0.001650890862846228, + "0xc73f65Ea9d3d3c165cC6Bf31dE607cb946B1e4C6": 0.002086677225362585, + "0xC84FAc7D2F80D70b21A536Fdc1Fde5cb404d747B": 0.00706528481413282, + "0xC8a4C0aA604f225aA006835672CCb68e661f7Dbe": 0.001023872103175712, + "0xC8d23C39c8F808D599b65D4C9eED01B8580a66bE": 0.001660993596091826, + "0xC92b2aF1B472D39275181f502b9d369ad9507DbF": 0.00021049570852914, + "0xc92f8051ae3786fe90CA5aB89361DAD6730c4Eee": 0.001914942211312756, + "0xc9B1B3Ad7546703a9AcfE2940287ae7F9CCAAB70": 0.002884264749883987, + "0xca30cE2505F78e7B4f07b2d0A0F22eD62B19051B": 0.003023154432565645, + "0xca49ed45A7d23193b0Bd2BE322D4F0C63168b34c": 0.003175292204874449, + "0xCB4bB9D616f27dc84a256b768B4C393fA8010caa": 0.000384449569462733, + "0xcB4E72E300390B3E352f20787300CB741fCDE09E": 0.001485087259569859, + "0xCb8c77837f470053F91E1e288CAc223118C69937": 0.000520092891168132, + "0xCc50808A98AB15312361ab4837f412B2d9cDdA38": 0.002129457522390259, + "0xcD6DbaC9cFd5b348744640D8ceF05f1B5245e2E0": 0.002589611500333746, + "0xCD779f2e141fbA5A332A8Ae7882Cb1aD86cB8D34": 0.002958572598237754, + "0xCda9C44C18c5C83963aeb1681fc4198542650345": 0.000899944832054884, + "0xcF2e28E5E57461254B8B254AE6D03c89d19BF743": 0.000612845037124201, + "0xCfc1D59675355d5288C982d23caF28a2D0A6d48e": 0.0021166793112989, + "0xD02524BEeFd5164Eb28C77CD3eb2C7De887B891C": 0.00072549399647567, + "0xd04383c1e5Cc572BDBebBB88a1292F9aCe70007E": 0.000875459348520922, + "0xD05F0F552d72947b471a4C4BEE98F9207E889482": 0.000357507395322018, + "0xd0A530121747B005af6Bed69426092cB525713d5": 0.002258230098316503, + "0xd17EB770E4E209C186cEDA0d7E09bFC03D792b36": 0.007854743410674207, + "0xd1Cd2FD35C63e27A33f0b5ECf9C92ba1AB9c6dF1": 0.00046190163348943, + "0xD225626025F48Cd43cb35CE935a4F4B856AEd21b": 0.000617205280198213, + "0xD25f7e77386F9f797b64E878A3D060956de99163": 0.006008179777689715, + "0xD27122760634f46994815A2B5097FFF7b0e910D5": 0.001450915497136981, + "0xd273f87e43851Fa7f0518E3B385c0d964621E3c6": 0.000544471694479184, + "0xd2Ad096Ed0757dc4954f66765dea737e5a687dfF": 0.001742186993010333, + "0xd48010De315e10D071853b1466f0C273e766FA07": 0.002784464923297565, + "0xd5769DCBa4D94716e860431Be65c0c84C379fFD3": 0.001324700945656694, + "0xD593f878270b61e64fa65dAA06728D0bA89C792A": 0.000820867618037016, + "0xd5E10116D747EFC7028fac192093D2AA2Ba9EF12": 0.001676456834983982, + "0xd65e71C781BDd00221eB77B920298663D0b83484": 0.002211278863920194, + "0xD6CCf8Be80aa6ae4320AB4D6551C6f3ef96AF7aD": 0.000486618749418646, + "0xd706bf4bb1560a73790D91B8fd585Cb5508db6ea": 0.002308707028848392, + "0xD7D00580798FA514bbe9b71F3B84209f83Ad5bE9": 0.001984546563744876, + "0xD8C3cd1A7576efC723357B7158318f0CeE0e30F6": 0.00044068200908034, + "0xD8c50C68066eFE49bC12658A5D7C984E7254D417": 0.003099888050457143, + "0xd957f2298bEFD78E946643602fe04509f45Bd5bA": 0.000230977753115089, + "0xd9e352554D0e4269d9B158d1baFC7975fd4d402C": 0.000760604591941388, + "0xDA6De31eB28a648884247708385a0B8027E6C4b3": 0.000790580459432837, + "0xdAe56179CbaDA38DB0A15da62D43Dc66306f746B": 0.002320295461415382, + "0xdB040b1bAD2941e02F6fea3a7f4a13D189E0beC4": 0.002004344134765031, + "0xDb6D77A78b4da7286E3C1A6828EB83D9F0cCA527": 0.001093054549561128, + "0xDbD9416f32c409b3c7A29655AA515bd717616470": 0.00325733870134353, + "0xDcb26b5dBB5F8798C1b434597ffa5e4aEca20d05": 0.000800468300315379, + "0xDcdc4E48c3DA83109322E3fC507181D65687Ef84": 0.001603467669571091, + "0xdCe31D9b0a5B0E2A40fcdf9A2ad73C3CE2071C15": 0.003834170421679551, + "0xDCFCAEa66D61Ac1B52bcFB647c03f56c0bbCAa28": 0.000511457002624332, + "0xdD2CB8c9b8FCCDc366AE60f4FE1c99813Ec0d18e": 0.00832967187464946, + "0xdd877AE95f4aD48b4Dc640F52E802BcBE3301130": 0.002270430581135096, + "0xdE7250D923299e1EcEDc0743b159E95B945082d9": 0.000434934982653018, + "0xDEf3560E74E9569d32339337D6A05f3F329D7a3a": 0.002032296297916199, + "0xdf9Bd257d55271851b8F75613542635Fc608CFc2": 0.002101255931292738, + "0xE08A026bAaC28a95041DB74Ba78CE93Fb6aC766b": 0.000538361162153996, + "0xe0b343b462aB6D0d3048644D1a85f287D46FC23d": 0.002914688519788281, + "0xe14B7Bcb3A2A9b2EeA0a53dCE0A60F1649660C4e": 0.000266237354997955, + "0xe1810961A12B5B38468fFc32aF3b5F8dA1EFdB53": 0.000446224064526624, + "0xE19243a27D28a8Aebf138DeaE361b8AB53862a9F": 0.003641340331583464, + "0xE1d4C898E9720979c898e0962a1d8e3A897f9263": 0.001372531944753518, + "0xe251B115E89036C0bc0a8Ff09B36f77ef6291D84": 0.001264864072616305, + "0xe2A2f2A338EB923454e331422e9b6ef872325Bb5": 0.000843577679845794, + "0xe2A85879BE19fF727cDB79Bbee733b616e7c338d": 0.001377601143189636, + "0xE30C4Bffc186667d5dA5EEfB505B419432c62168": 0.001840082632911276, + "0xe35c3f0ad5972eC28773b31598527a9A0D0B22a6": 0.007238533487009321, + "0xe36b79317a75b08384c33D21197c7e3273886873": 0.001227236915685986, + "0xe57fe5bbDc76E8Af1448550cA56e7E36c8Fc8272": 0.000241820836428222, + "0xE5E7EB7B5E89866A6D852F55BFE363EFd50D2F19": 0.003478915545574645, + "0xe619ea101759B9D0c5dDC36b59f1F5e55FEB76B9": 0.002359796399082513, + "0xe63757E3cD485C9b35b3a972fFFA2d91B8649483": 0.000986735864247628, + "0xe67d3b0BDfd1D853FBcE6C0898b464e332a67B18": 0.001198794239274962, + "0xe6b5A31d8bb53D2C769864aC137fe25F4989f1fd": 0.000753074201404674, + "0xe79464c19fe30E6Db25A74aECf65AABeb92A44dC": 0.00163463112987963, + "0xE7Ff7aD54492A38AfB99bb5d8B897C5f93A66f47": 0.000643100129523618, + "0xE82C23a1084a4fB27ED46628c40301c0f63F0C40": 0.001196899433264345, + "0xE86A48bC1D340Bc524d5529222F5b51995bb8132": 0.002739279128097161, + "0xe98ED74D2AEd7b818FA01A839715A917D1341bC5": 0.001032817481176946, + "0xea03Af40FA59Ac9C311187Da0f9b979DA073C226": 0.001978266469119038, + "0xEBac3e24c3f59d50a713F2c79535acd381487486": 0.001976383990070969, + "0xeC2Bae309d0A18D7dDfD4EA0f17a2f60817f4E9c": 0.000645933072947126, + "0xEC67006aC513BF20ac599B48f1f9F725C142BB23": 0.000722736064090086, + "0xeeD671a75689E7aFda9F658c8482B0939bEE2d34": 0.000233600555683327, + "0xEEEba9f78590f8C05c67b627BB67bAF22Ad9597E": 0.00027391236297332, + "0xeF7220723E580F03A8f8b076Ee8623b1dF0103fa": 0.001441243816484446, + "0xF055cbe9B6b30D64AC1D7305cde7BA6c0993C86a": 0.005628685590980622, + "0xf0b7e13a31eC9D21c05fcD91f71CB82498864D5F": 0.001361374639710291, + "0xF0D9A0C82dCdE0675E2E796f6e25E8aec3e52f12": 0.000877071736336323, + "0xF1De794eCF521Ed64bDd4DD55308361511f87990": 0.003713800514850269, + "0xf2009F3E705e48cD9E1d29397fc19Fd7E4870cBF": 0.001693162005814965, + "0xf20737e48160A87Dc9D1B26D8B63C796d2F1EA91": 0.007088051537280779, + "0xF3579d18e82E8A1353D58D1B5a7265F4f5844A9c": 0.002003183311098456, + "0xF39695c39EaCdf81D146cE6667E81476Ea9b3fa7": 0.002222254263173393, + "0xF3C162C189341D024ee753223101612ABF6fCf9c": 0.000982476308149558, + "0xF45E1A95ABCa5362844634106a1B0705CcCcfA23": 0.00181078691486248, + "0xf5bE8850b5758acCaD467dA86119Db517b8CDe0f": 0.001529318310414164, + "0xF5C14eE163B349ccC50eBe31500078f745500580": 0.001221438452773522, + "0xf5DF7a18dF35dA5EcFff6D55bcF920e3d8F6d5Ae": 0.003188873408831, + "0xf611B9A9F0d9a0DF279665b05fE338b29d53744a": 0.000904891143724273, + "0xF7FCAfb56130a2e39bD28e5115E90E6972b83e5a": 0.00174590331797519, + "0xf882F94D9fA5a7bb883D3Dfa04e5A43Fa057C333": 0.002919695715752449, + "0xf8C9a3f1E55b9a91E413A8C8bB9F5f84C6d246cB": 0.001487950376516927, + "0xF9D3A0a21eca45C45F9F476Bb4Cb40c1C4f3aF07": 0.002179385491415533, + "0xfA8cE8D44271201e9Ce37838ccb75BA482d597F6": 0.00110276420745576, + "0xFa93E76Bb7de1071D6f9C0f77Af883c2a944B2d1": 0.00078487359042108, + "0xfAEF14B594cae1666846daB2780E964df8557950": 0.001783208136309095, + "0xfb043BBaF380A06c01750ce0a6324e38eD11110c": 0.000604414447549389, + "0xFB364E4D8eF3bf2551550DF01e0c8d55D3A772EB": 0.000958832180440529, + "0xfb4d1d353f95e477235611ed67076E61643B5614": 0.002094968733111619, + "0xFC2ed2462f05608b6a21cf1A43bf24a6Ea08c4CD": 0.001852574099363942, + "0xFcECa6193031F7f1336Fa055edFe96555644Dce8": 0.002026048122277744, + "0xfCfA494c13409172109f161C428499B39682fFa4": 0.001918027966172223, + "0xFd0Be09AAADaAb67523e8c6a9A3c1D657aCB2B5A": 0.00457870320961811, + "0xfD8355b24aB8815cA2d76d1E495DC29B4330241f": 0.002577673853038057, + "0xFEAB4fFA81BCd17dFdC2d7e906662527697915d4": 0.000369892464405737, + "0xFec5287823f5a317AB879eF8F8901Ad21c7D915c": 0.003531197597318023, + "0xFfdBD837ADAe8558684111d4B5cf9Ca36F58569f": 0.002119049556324283 + } +} \ No newline at end of file diff --git a/packages/affiliates/gas-rebate/corrections/Rebate_66_Correction_Manifest.json b/packages/affiliates/gas-rebate/corrections/Rebate_66_Correction_Manifest.json new file mode 100644 index 0000000000..48f55c23b1 --- /dev/null +++ b/packages/affiliates/gas-rebate/corrections/Rebate_66_Correction_Manifest.json @@ -0,0 +1,30 @@ +{ + "version": 1, + "name": "March 2026 Rebate 66 VotingV2 correction", + "votingContractAddress": "0x004395edb43EFca9885CEdad51EC9fAf93Bd34ac", + "outputPrefix": "Correction_Rebate_66", + "audits": [ + { + "rebateFile": "gas-rebate/rebates/Rebate_66.json", + "rebateNumber": 66, + "fromBlock": 24558868, + "toBlock": 24781026, + "minStakedTokens": "1000", + "maxPriorityFeeGwei": "0.001", + "maxBlockLookBack": 250, + "transactionConcurrency": 100 + } + ], + "expectedDeltas": [ + { + "rebateNumber": 66, + "address": "0xf20737e48160a87dc9d1b26d8b63c796d2f1ea91", + "deltaWei": "7088051537280779" + }, + { + "rebateNumber": 66, + "address": "0x2a9437de0ccd4fd7b7d98831213acedefc7a1092", + "deltaWei": "1902006430166225" + } + ] +} From b255ab20c963c6b3e45ef6390d8de2beaa41650d Mon Sep 17 00:00:00 2001 From: Pablo Maldonado Date: Thu, 30 Apr 2026 11:03:55 +0000 Subject: [PATCH 4/5] Fix Rebate 66 correction payout artifacts --- packages/affiliates/gas-rebate/README.md | 22 +- .../corrections/Correction_Rebate_66.json | 1174 ++++++++--------- .../gas-rebate/rebates/Rebate_66.json | 644 +++++++++ .../gas-rebate/voterGasRebateV2Utils.ts | 10 +- .../gas-rebate/VoterGasRebateV2Utils.js | 100 +- 5 files changed, 1256 insertions(+), 694 deletions(-) create mode 100644 packages/affiliates/gas-rebate/rebates/Rebate_66.json diff --git a/packages/affiliates/gas-rebate/README.md b/packages/affiliates/gas-rebate/README.md index 8ef27c00e7..1ddf0a96e4 100644 --- a/packages/affiliates/gas-rebate/README.md +++ b/packages/affiliates/gas-rebate/README.md @@ -44,16 +44,16 @@ yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet ### Environment Variables -| Variable | Description | Default | -| ------------------------- | ------------------------------------------------------------------------ | ----------------------------------------- | -| `OVERRIDE_FROM_BLOCK` | Start block number (overrides automatic date-based calculation) | Auto-calculated from previous month start | -| `OVERRIDE_TO_BLOCK` | End block number (overrides automatic date-based calculation) | Auto-calculated from previous month end | -| `MIN_STAKED_TOKENS` | Minimum UMA tokens staked to be eligible for rebate | `1000` | -| `MAX_PRIORITY_FEE_GWEI` | Maximum priority fee to refund (in gwei) | `0.001` | -| `MAX_BLOCK_LOOK_BACK` | Maximum block range for VotingV2 event queries | `250` | -| `TRANSACTION_CONCURRENCY` | Number of concurrent RPC requests for fetching transactions/blocks | `50` | -| `MAX_RETRIES` | Maximum retry attempts for failed RPC calls | `10` | -| `RETRY_DELAY` | Delay between retries in milliseconds | `1000` | +| Variable | Description | Default | +| ------------------------- | ------------------------------------------------------------------ | ----------------------------------------- | +| `OVERRIDE_FROM_BLOCK` | Start block number (overrides automatic date-based calculation) | Auto-calculated from previous month start | +| `OVERRIDE_TO_BLOCK` | End block number (overrides automatic date-based calculation) | Auto-calculated from previous month end | +| `MIN_STAKED_TOKENS` | Minimum UMA tokens staked to be eligible for rebate | `1000` | +| `MAX_PRIORITY_FEE_GWEI` | Maximum priority fee to refund (in gwei) | `0.001` | +| `MAX_BLOCK_LOOK_BACK` | Maximum block range for VotingV2 event queries | `250` | +| `TRANSACTION_CONCURRENCY` | Number of concurrent RPC requests for fetching transactions/blocks | `50` | +| `MAX_RETRIES` | Maximum retry attempts for failed RPC calls | `10` | +| `RETRY_DELAY` | Delay between retries in milliseconds | `1000` | ### Safe Chunk Size and Validation @@ -206,7 +206,7 @@ AUDIT_MANIFEST=gas-rebate/corrections/Rebate_66_Correction_Manifest.json \ yarn hardhat run ./gas-rebate/AuditVoterGasRebateV2.ts --network mainnet ``` -The script writes `Correction_Rebate_66.json`, `Correction_Rebate_66.audit.json`, and `Correction_Rebate_66.audit.md` under `gas-rebate/corrections/` unless `OUTPUT_DIR` changes the destination. The `.audit.json` file is intentionally git-ignored because it can contain large transaction-level evidence; commit the correction payout JSON and `.audit.md` reviewer summary. +The script writes `Correction_Rebate_66.json`, `Correction_Rebate_66.audit.json`, and `Correction_Rebate_66.audit.md` under `gas-rebate/corrections/` unless `OUTPUT_DIR` changes the destination. Correction payout ETH amounts are emitted as decimal strings so they round-trip to exact wei. The `.audit.json` file is intentionally git-ignored because it can contain large transaction-level evidence; commit the correction payout JSON and `.audit.md` reviewer summary. ### Overpayments diff --git a/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json b/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json index 109476ebd3..352915cf7f 100644 --- a/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json +++ b/packages/affiliates/gas-rebate/corrections/Correction_Rebate_66.json @@ -4,592 +4,592 @@ "fromBlock": 24558868, "toBlock": 24781026, "countVoters": 585, - "totalRebateAmount": 1.0957668608098379, + "totalRebateAmount": "1.095766860809837881", "shareholderPayout": { - "0x000000000000f8E4fE2a98574fa81C728e340764": 0.001623200791717199, - "0x0013Fec13D8e4bd86AF7a988087B697ca1057B88": 0.002070984318620129, - "0x0024A67e0b91131d6978e1e0f72c94497bDBCc35": 0.001982718698536916, - "0x005CDb3B0B0964569ce0aCbEF483443296cE704B": 0.002337951423375661, - "0x00B64e31a3C6f59b2120b50b8741584f024722C7": 0.002629035364475586, - "0x00C3C106D11322c7aafECBF248cEE710ae3f0a5B": 0.000597858515100745, - "0x00D71C4FA96e518dD54E459114408e7aF9297C15": 0.002392552700169229, - "0x00dd323d8f4bDcEa52EDBdE935C1ee97C009c5a7": 0.00030078413245808, - "0x00Dd84F50e5699aA9F1a9f4f52c428BB305189be": 0.002254650304625379, - "0x02153ebE18bc66C57E540423E69A881a70823d40": 0.002618388898398077, - "0x04AD0F62A66bf8FfF774676a792E88D10942e2A5": 0.002084882404298553, - "0x05C6A4dA04bE965B659aF1365314bCade309bB82": 0.00124088623202724, - "0x05ef6560a7c9C2951B35AFea0868382487e9B77F": 0.001449839720952172, - "0x06Ce05Db7D0A4539B3eC2fa6b81DFe11a32120eA": 0.00213402154104884, - "0x0724CFd1B40f56B506136D5A89EedDda31deA725": 0.000435114378111624, - "0x074F2CCfB2716fC8B6aC579173f1aAeB1f759d52": 0.002251043091099571, - "0x078352359cBd47652b6aF7dC1c46DA5Ad1378035": 0.002534179075446767, - "0x0788f0420961aE4806fc4Cba0898A9ca0300eFC0": 0.001227657140494814, - "0x07f88CeD359895Ef9CE4b3A09746954e7eDFf139": 0.001343042563385011, - "0x083083Dc8dE34B1dB09910ebC8a8Ff7a47C546ce": 0.002725193807169186, - "0x08610322dfDa1dd2D129b647e13840e832D485e7": 0.000357972841447646, - "0x088887cCa9F1E0a6a4D42BcBD3e107686bda2486": 0.000670860511931726, - "0x0894f897CE9b108cDB97C239e4f96C407a248e92": 0.003149757188583824, - "0x089773A760FEE0F1A3D3ECfADf4b2E145FD1E88f": 0.00169629330901413, - "0x0914Bf3e3DB541a79f6587F83A921Eaa368CAeA3": 0.001110997322694742, - "0x094DB477152D5678A0cE5e263C284DFf1052700a": 0.001250099351514977, - "0x094F5F0706DB7e3715a87Bc37437f2E6e6029B3c": 0.00056259881232371, - "0x099aF188E9c68B91617EfE4b09Ee8CD90ba4c63d": 0.001958173934655549, - "0x09a10823b87Aed0A3c348C0a20d69d3276192913": 0.00106930717885286, - "0x09C1579AAE05524f455AC4852d60C3e973ad0715": 0.00328306669870331, - "0x09cD0D28125587e39a29CF25Ea3f7851C585738f": 0.000532900234024956, - "0x0Ab373B6D140dCF3919E17D277Ad1Cb818B1EA53": 0.000598416251823648, - "0x0b0221d279026aC38eec4e13408BA7966Afb9FEe": 0.001701370489208542, - "0x0CB8dA6C265a90B3CCE8431267c0A94a7f1db875": 0.005838128588386673, - "0x0dD7762E2fe09c9eE2F5aCdeA19C102f7c16D8C2": 0.001237634310364501, - "0x0dFb17299E2b39C63602Ee11BdDf9688Bb66449C": 0.001491818707670364, - "0x0E054B1F4b103A1C92866B3205EcF818334caCf0": 0.000265937422231955, - "0x0f8fe8e8B7Ad38615904a08e821E875fa19d8b67": 0.0039965363551254, - "0x0FaD7Fcb19f3EBe9402BF0623d7ed0FC4F1dEf15": 0.003798075899170629, - "0x0Fb0e2fF6739060A811190b94b6D7da786735be0": 0.001649341817605003, - "0x1098874e7b4435615CAae49AF275B22e195A574f": 0.004958508195265784, - "0x10D6F9Fee0d48E7db7279AE0139cb5b577bB5516": 0.002686585110209063, - "0x114D4348265E8302980e7BA2db441FBF09EC3303": 0.001605566072098302, - "0x126db3213b309A8D554594e591e614425cCaC78e": 0.00210489624540066, - "0x12abC23621Bc6a6217c8190Efc21Bce9e0cad459": 0.002036727767680347, - "0x132DA096d35f9DeA0FD7F348232582DA4e551dA0": 0.001911522861608885, - "0x1379D42CC081790d6205712b79f6E133d798af81": 0.000929662792426936, - "0x15856FdCA72b0429E6E2117b7675dC2b0E6272a7": 0.002142293956414096, - "0x16D12711626310b5894783ca187BdAfe7aa4597A": 0.001347869592891393, - "0x17e2eA46935588BcE435278Dfc4Ffb31F8039BcE": 0.003101468775876044, - "0x18fEe6e511646B8ea2e4964277574F637Bc03f3b": 0.002979943874029252, - "0x1B0848A69E665eEBA88bb877b67145789d3d8b61": 0.00294200765490773, - "0x1bA4b6B2e5864838ed336495eCE7f456b1ba1FBB": 0.000271516145173994, - "0x1Cd79a62361Ff4AE9CFefdc128A255B1495627Cb": 0.001094860335258598, - "0x1CEe194Da1eEfe344fb2e7f46faB7D3A65C078e5": 0.000554433439102433, - "0x1D1C0E8394e6619Bf75C0F2e9321B3D324409283": 0.00234538028077862, - "0x1D463047F4c954D70d2718AdF96c43f24aC19dEe": 0.002720351640606777, - "0x1D98cAEFaB4bb543d98Ec6136E1498c34AF32c85": 0.000905622562308438, - "0x1DE746BB64222C304b38F84613745323cB6C7fC1": 0.007710366790600202, - "0x1E1486d4c30fA85E7fD5AD87cC7DcA15a626374D": 0.001704259387520791, - "0x1EdB50d83f76382480886597A3023fC318B2ca66": 0.000480554189311596, - "0x1f12254be217Cf9E9BE46960c36970390b07f16E": 0.000564319584213034, - "0x1f63E3125AE5b76240954F78dF62b4684CD88c25": 0.001171153912008066, - "0x1FA1C17dc5dAA02730b97B7a9b9D75710244d98e": 0.001403209286460627, - "0x20271eC8650e0990201EC5c785a5f3E8b51850ff": 0.004044210483401355, - "0x203F9674bE9782BC4B194625Ee9dC6800e65B2D8": 0.001117684671989674, - "0x205a89902311Bb2c44668d5712D7a21781279150": 0.001085309373654446, - "0x20A0fAb3e883852228dC2D54f4fCd4ceB6b6cd68": 0.003650632091718417, - "0x2108a6d1f32D1A932431d64E3328D1d45bD0520f": 0.006374040071022786, - "0x212df1ED15FB55607f180b8E26dA4A3db66b04d8": 0.001398354506323405, - "0x21681B5fac7Db2d8DD027487FeA9cd28B5c192A9": 0.00425641869693439, - "0x216bf62B05246bf4a1694061E8769464A6BFD812": 0.000584902357161496, - "0x21a27324B609e864882778c703FFc42Cc05daC40": 0.001894091978422001, - "0x22992D673Bacd1a43508294fc00597158a6B5816": 0.000340594444861752, - "0x22B95B36a3f4a7dC952765f9CC110ab455Ff6E4D": 0.003513543769493914, - "0x2352E748C9C090f44a8418f74457554CCe8D0485": 0.007120473344033869, - "0x239a01C50406Cd2d5943B408b49b32226741E1CB": 0.001367521023877095, - "0x240d2243D90E8968D0c8E807202bC8a2DE0dC53C": 0.000230780779968753, - "0x24eb1c355C05439819a23DD0842D5D038d1CA05A": 0.004296183001431525, - "0x24F16D0Cda8c2De21c762E0295C28d7249a972A4": 0.00309793217410008, - "0x260D417fBD1716B1375CD311f8a6677c4a780B3A": 0.00214937623772284, - "0x26fd27a26a6C1EdE36214512ee4E56440a0cEbF5": 0.000470793957213322, - "0x27064Cc4FE5bd5a20d0e5A21390a45F5a44Bf7D3": 0.010849346915887568, - "0x27459423cc0f816D965A97dCB90fa45774a18C3A": 0.000750370507871038, - "0x27b7A1b3c4A872FB30cF22e8716596a2312CFD2d": 0.001857557792118634, - "0x28cCfB369Fb97929068Cd30A390D37fee0037C61": 0.000573788814505132, - "0x28eC3b46262c614df6D5A3FF2726c9746F1d1675": 0.001541893574210529, - "0x295c5B0C1D5acEa1A94eDcd67005aec356ad1c7E": 0.001808342328838047, - "0x2a9437DE0cCD4FD7b7D98831213AcedeFC7a1092": 0.001902006430166225, - "0x2b379bFb86e900fE8f3A1434ee79097Aa5b883dc": 0.004023124829165172, - "0x2c26767989D49215d249e6D36F8e3FE2717f7DBd": 0.000046626720589143, - "0x2C281042A8dc2699e4e2BcDac11c2810dd40d8Ff": 0.001671269695907393, - "0x2C492138498165C3f6fF94Ab7d0B7Ab6dD546AdA": 0.001042570356273628, - "0x2d14a06687629C8e0F9fcb985814FcFfb60FD36F": 0.002804508864017687, - "0x2D29986ad59F77676c204d09b44Cd8Fc9EE7B6a2": 0.003084938156140876, - "0x2dB601b85292C8c94E87BAc3e56B3fD19CA45063": 0.001955301462889607, - "0x2EA989edfCac6531cd912d09A456f9809BaA5377": 0.001248519426706471, - "0x2EC20e5aA17F736060356f6B186208D5Ce0aB4b4": 0.000401416864313636, - "0x2f55877D6D8A42BD87e0325201cD15d63aBf5866": 0.000522007119886494, - "0x2f8320C2Dc28681Aa5BBF92e79C37BE656a7D5F1": 0.002442970611304262, - "0x2F966072f36109F27539E5EdEfA741912206E491": 0.001030197369633942, - "0x2fbbA6606C7628b749C6814fBAc1f88fEB21aeFd": 0.002728062359897463, - "0x3009e81f3b145c71A409313306Babb0AcC219aDb": 0.001007745932840434, - "0x3081508f0cD453Dc99Bbda26ab35Edcd785cdd88": 0.000535939904748932, - "0x30b2DAEb3757B6C7462cd0D776828F8d7398BE50": 0.002955698206664348, - "0x314FDb3cE492ee03a0eb037De01Ef53757C73936": 0.000773119450595252, - "0x31C44F5af149d2C9374f6A4d7253d0Fd69b127C9": 0.001039654649858049, - "0x32006a2557954336E877Db126A25e4ac27897C86": 0.002001533622567478, - "0x32a27a34B002aDE54C21515f77593E2086f5E7d0": 0.001904149153193711, - "0x336701baB9Ee6a829a5d610A301E978ACed202C4": 0.00105201937374925, - "0x336B9DE28D67D692C31DF93A9b8630B2Fa50d88f": 0.002417887862933094, - "0x33dfc8Dc28853A4f9FC0ec04BB2B67C6379CcA7f": 0.000609674711855852, - "0x340B8E5B52619c0ade021F806348e11274783740": 0.001392412572417687, - "0x342F40FC637e631f669a5b38fA4fc94Dcdd7DBED": 0.001285220148936264, - "0x345B46fCF8E503AE3b89174a59C04D2D212A5a10": 0.001982372603469258, - "0x35A7f9DB799649908688826E06CA754Ea0153724": 0.004068294499964118, - "0x36Ba943373FdE856457511ef8E8955323174331c": 0.001304975240793567, - "0x36Ce63c738971B948Cf0Afb842b7617254C15BC0": 0.004321177405122993, - "0x379570ffA1A60790A8B5955cf643F868D6ad4c9E": 0.000531220997599391, - "0x37b9171eF596Ac6A57c1d2598D71345e2206A5E3": 0.001944819017097703, - "0x3800Ebf79fE712781916EDBeDb169bA295dce5fc": 0.00080065779667571, - "0x3895799b03759423C728Eed3aa0C0414F5179f79": 0.00103015959453971, - "0x38F855e64542641f9e254f6e527351b55b560C0e": 0.000707484196836413, - "0x393950505b160607F40D11AB956C9406DBe6e4ce": 0.001439077395382837, - "0x39ad454BAD7d4909137cDAF1193cC847eFA959AC": 0.000998226306326582, - "0x3A4a969169aEbAb4e9AC667C9aAC62DC54c53A1b": 0.001661521763325315, - "0x3AbEBE2bFd423dbb6357674476D44E9bD178817d": 0.002273991452265629, - "0x3b59d6B33E8F8dDF9734917a40056D07548a4444": 0.001128045778703466, - "0x3B7236C911F87fD75315c4Ed44A1D2EEd725Ad14": 0.004678752876715251, - "0x3b84E3FFBe845c0349E258f243B5F00cA22Ba587": 0.000404368233109516, - "0x3b9fFD4CeFFd768DF16d79e7492A1BFfD087C44f": 0.001969189304064087, - "0x3bcD8de636cEa72178D8f1285f5Af0dd02d0B142": 0.001867467103399945, - "0x3Bd0cbC96186Cc3eafB304111e6Ad20a4Ac92F8E": 0.000431880615588246, - "0x3c56D7BB7b81282a369920F4816D75eFfc549b33": 0.000212558777040274, - "0x3D65eD138686e2AD54006d4Db83aD4597D645370": 0.004183334831553569, - "0x3Dc3862Ba073D508e421671c7F44e9Ee5d6B33CE": 0.001686882027902168, - "0x3e1B1A4a8fbA26E80F4678d3eA3AC1DAcA78523e": 0.003125073719379432, - "0x3E59864442ff8e0043b5360Cb134F6Ca2d514152": 0.001862838207470264, - "0x3F180F32AeD8C10Ce46065e05185Abc69F1D70B8": 0.003428894356078606, - "0x3FB7d3E1212cee588b14E57aE9A50eD93eCa0580": 0.001483608671467378, - "0x4010650464cc07e447ae10d3135F8c82554b2528": 0.000534635647165048, - "0x402bED71F1B26a068664C12818ed721E37155A44": 0.001992875732155986, - "0x40602DCAfbeBb5635ede96B2EcB94d534fcB4670": 0.001130821318515792, - "0x40bFe49745Df251fA0Ac7a3f983101FF170c389b": 0.000451794451432436, - "0x40fE8993df6f3915540aCE94E3a3d86a48829664": 0.000563271918036863, - "0x410fCF90a3805DFba3939827b0E75bD5fc2ef8B3": 0.003074690002145242, - "0x415106767827A7856D826458a486a87e0e15097C": 0.000452424928595454, - "0x419d955a9C3dF6A1b9eB3EbF2d21a3C63A8d57ef": 0.00400654081690959, - "0x41a1F47F710841F2f4cf492149C205725875f400": 0.002325962715286745, - "0x41DeB171107fBdBb7290eB4a8E77142c4636C13A": 0.001894591765754071, - "0x422Db8FD3778343B595762417b62474919eFeD41": 0.0019755448305781, - "0x4241A9998720cacB5902cF887A5323Bb316E3166": 0.0008062558287423, - "0x4241b7A1b190F97213cc092237833305af62f563": 0.001076317288004069, - "0x4289C656B76B20eBF1B5Fa4363dA812346919bdC": 0.001136506580316892, - "0x42a786c945032Dd0AFaa89fECB659789b56B3FfC": 0.001902747861644057, - "0x43E6887aFcF79DbB6aD9c0B22f802B77fd7c6404": 0.001950850611772753, - "0x4442dD25DA06786c78d8874fB33381E706877FeB": 0.002045392642312193, - "0x44C642f69a39F1b2b788C013c3839277cBb24DF5": 0.001983616606745826, - "0x454fd6d5FFe4780577ce64e7B17B39BD80158021": 0.002200839051644971, - "0x461980B8560EAC362aE5E685cB5a35952714611B": 0.000992761419614184, - "0x463bECEc49d10Dc785110031B9F6AfFbb84b6aAE": 0.001304490755382015, - "0x467c3C9D910fF352c7472571d3360bcE53c2F6B9": 0.002817229027824432, - "0x468876cB9b5850359609Bb4Ec7977a3f41AfdF75": 0.001203599383669484, - "0x46Dd430cD21e39ef9A06b40406BEeF25B3810210": 0.003142803920990852, - "0x47A40A367b3298BE3da3BdE3994c5342e26f368b": 0.002574440801490452, - "0x484637541D68ec3627Ae6E2bD7192E167b88E93C": 0.002889776300040188, - "0x48767f20ec0aCA7f47b3dA2Cc32Bc06549470A9B": 0.000519569925810646, - "0x48A384D082C97f82ABDaC55e43EE8f2392b9f394": 0.004047524464547004, - "0x48c7e0db3DAd3FE4Eb0513b86fe5C38ebB4E0F91": 0.0001090248, - "0x48d26F8F052d80E943694360899C4bB83344FdBC": 0.001719069438432509, - "0x49135912edB24205E1b0E7b9eA71887edC59D50a": 0.000421542883416198, - "0x496A936f46dFaa912F128CABFA01BA6F56a520c6": 0.001115920301574156, - "0x496cdac4854423c66EB0Da89f9e96Ef9D8312ef8": 0.000876634598008012, - "0x49b3fB1B5E6C6Ae2A0F15dE68F73F9e5Cf99Bd78": 0.000165806687619094, - "0x49BA7fC7a31b6d49e0C7eDcFF76C1678078EC8F2": 0.00030506313509658, - "0x4a194280157860E8aBfB7446Cf9eE84bf66dC839": 0.001650531881154534, - "0x4A2e4FD85Dfe564C5b14A134AcdFcD531a5BdB92": 0.0003379454536506, - "0x4A6115D5ee87a3Db90b47881B7d6e29802DEe62c": 0.003829541985395866, - "0x4AF5B23Cf8B2EE85Ca974DA6a51fE12bF726Ae6b": 0.000477202257309814, - "0x4AF80E6414EfeD0B91FA19c0D19B46C381beCB7c": 0.001131272892735052, - "0x4B8aef878255F6242606Fe5e73D659004F5A34fA": 0.001585130521359351, - "0x4C7D5a6437B325A998f83d9dcC267c5fdfF8ef56": 0.000772818599011801, - "0x4C9B462e44B14df09912D99Ca7a0daf9fF0d6f77": 0.001411727440103071, - "0x4CD6ac17782D95DC7a8eE2106fF8de4a52984B01": 0.000235348811664286, - "0x4cFE0198958D72546c4F8E415616B4594DF18679": 0.002801481749290462, - "0x4D2141b31437E970A0f13c935180194a8C4308C1": 0.00205394078474958, - "0x4d237f8E3364Ac5104765d287cDDFbD52b3C621f": 0.000257312493278815, - "0x4Dfe8442Ad63763E7D143BBB40F6A9A76F86a551": 0.001378504412637978, - "0x4Ed43703F882CcAC37897Cd46c80e0462be5C91B": 0.001671144164619649, - "0x4f49D938c3Ad2437c52eb314F9bD7Bdb7FA58Da9": 0.002205644371239276, - "0x5002a9263908CAb85BB4c71559227647F82530e8": 0.002916957364213548, - "0x50229CB8317ECF297E65cdDBCe88e0814eecdf9E": 0.002130687755108406, - "0x5060020e66031c324f77ae24F14Cfcea6A688Cb7": 0.000436805264451654, - "0x5071e6d385f584B5875166563c1670460905ad7B": 0.003897061222411612, - "0x50d26FCb38a279043bA075B86df912Cd523931Ef": 0.00099617178833104, - "0x517E758fb4095a1D250D084eAF16DDd041577A05": 0.000418521973844092, - "0x52A11a19528DE46078fe1118aD45540A5ee514bd": 0.001302019002861303, - "0x52b88b1f9e4B0E8B3738c2f4AD0EcA5B73ab31F9": 0.0024326559705695, - "0x533758cC4EDF0568E51e322367A9Ec6fbE24E9E7": 0.001557848461192187, - "0x5381B78AB971afD2ecd44F1431D635541aca696f": 0.003438903181023736, - "0x53A30736a43c413Edf5C13F049D34d3Dd57B7128": 0.006332039302005524, - "0x54B74D49cbfb92343E4607F260BE721b208b4dfB": 0.000362656876207634, - "0x54d6390e19Ce818209bD3B53a5d0D2E0c6FaAe04": 0.001099071979430954, - "0x553E206F3F504c3E02258cdB93614e0115827D1d": 0.000995348388598626, - "0x5576023B904E1EBE5c35c7C041bbb2806e890163": 0.001551113132212002, - "0x55AabbfA2e5D574F24aF480E181355DC788E0Cc6": 0.001550301160922042, - "0x56719d9844bb7968941fe7942462Fc38D7448896": 0.000351628609946178, - "0x574c891acEdddeB18d112DcE69F87241794307c7": 0.001001537126390391, - "0x574Ce8Eb2f3BDC44Beb64eAA9e629004276586d7": 0.001841006912831389, - "0x579fFc05d22484336b803DE2201Ace27A5Ef5e0d": 0.000683903625555655, - "0x57b92dfC53d2D50135946b74C02f0E8c472A2f11": 0.003034112585321238, - "0x57c106cD365B436aC4a2Feb8690CC29FB32E8773": 0.000558955922466647, - "0x57fDd988547aEFA02dDaAE980AAfF0B031924D3E": 0.001241214821572192, - "0x5836Df3DaA6E9B97434F77272a3e8ae3c478D0E7": 0.004138713207712326, - "0x58504a178E3A3B8B65E51a9014679550f1dC5a86": 0.001830886196590977, - "0x58706B388caA1D46091F1FE4559F6BC77402B44C": 0.002665148578325707, - "0x587Cf3Ea6bdDB04A5C6912AC95120443f4474115": 0.002277413218547596, - "0x58CFC8ee2132847AfcDc67CdeFA92b2D21eB5Ba9": 0.000984847744131868, - "0x590a8DaE6861CDc2b0300096ec6E4dc6cF2143F6": 0.000405833426453988, - "0x59760d82C6c5B6B6F8865093820B74B5325d775f": 0.002091237757157023, - "0x5A7c9e40Dd0b4173d368c3A810E5fef2E92F73a4": 0.000555494147591108, - "0x5b01ce79D8b3B793DA3Be5e27de3A767f1a02eD2": 0.004090213034835558, - "0x5Bb7e188594870CE0296CC083aC74C35B2565709": 0.001189219689035914, - "0x5BC3D8339754B5D4455355B3C5CF2639fB943942": 0.001058707797710202, - "0x5c4907bF26883c8dB9cd38F314bB4DFf710593aC": 0.002828673988841977, - "0x5d2150E5d88A30d5793c6C49959B8f7d350a36A5": 0.00062317021023243, - "0x5DB732749c6871540f481c15eBF353fC03c225D3": 0.001579445299430718, - "0x5dC0A2903554A228D9331ee0748F1A712d1E6d39": 0.006863964665223741, - "0x5e4180eADCD9328c0dbFBDAFcFfa73c8eF831Ffa": 0.001782939204355069, - "0x5eb31519474Aa90E492168a403Fc2AB4522ADc7b": 0.00143006919015883, - "0x5EBC1D2809f4DfcA9Cb518EFd2307fDFFC36D55d": 0.004396707672251835, - "0x60307A482765634C9fdb773fCF4066bf8614df8B": 0.001786812667424917, - "0x60CACe9B90E3A1E6e49b1EB16BdA5fA631cf23A4": 0.001752650545741213, - "0x60e0D8fef5d86615067dD713cA3ecCB2dC669993": 0.003183531176946441, - "0x610C6f79839DDA54E8a587e279E6e93a0BF589c8": 0.002039304527156259, - "0x6137A7c745CE7ed7a6eC8cA4AA5B635fF17d5467": 0.001118648746654506, - "0x6147d56b02faBD35cd9fC2B80a60276cDf089521": 0.007326360624243218, - "0x614C52345D9a2542460a765B7332016BA73599e2": 0.001361811851143692, - "0x6209e6ABfEE4Acb6Cb6C2d5FF8CAA35CD9B87984": 0.002448488320059453, - "0x62A1Ac16f4Bc32Ea0B65795031E75419a46F8F01": 0.0040086091843321, - "0x62a3e17519aBCE8b5B12A92f3E01bB6b5CB09751": 0.00192670093424056, - "0x630A63523A4f079201fb548114695d8da1d742F5": 0.00044897364183439, - "0x636223B012C4d186153CDDd584F3f4F733257Df9": 0.000939801620133649, - "0x64125D5e793b05F0290e4d322a5b05Fdd3EC2674": 0.001317701293673964, - "0x64230Ae13E943e41450061d01f38b606E6dc996F": 0.002025486495699609, - "0x64dbcD6e381a4833049cAFB83eb6f441349B2F48": 0.001279016189798426, - "0x64F86C703002b9fB260C2fC65C15ca0e65530fd1": 0.00176381571977205, - "0x6573e30Ee0ad46BC9aFA0C2aDb0D3f147D658EFE": 0.003157830075647647, - "0x65DFdAec30d18F98791153A92F1f4cbf64839Da5": 0.001171524258265209, - "0x668D123f7AaB549301D9444E582Ee4ccd379C4f9": 0.000256239437651421, - "0x66A93EA89C257a03a125188f8eB742972537bA85": 0.00289610883123106, - "0x670aC9fE190AB0Ac2D6829eE414F221794B22cDB": 0.000367961554486094, - "0x6748445D83259a6709e459873323324a54072d1B": 0.0004125245335512, - "0x677350145860d4937CC04bbD29333C321862Cd19": 0.001810100757137645, - "0x67b4329df2274F21429538a1Cd35bF604C35dB59": 0.000617427740993167, - "0x686c4D2ce918805D05FD93F109e279b0c3DC8Bfd": 0.002697900891135362, - "0x68Ba3e38585941E2aBEc12e18c6AC11E15052292": 0.00120725538056029, - "0x6990d1288EF65F0d0AD9E2c54d1ABc91118C64ee": 0.001512452283223035, - "0x69D0341d380a1229f4751a0A721345dBc716586C": 0.005333525067475858, - "0x6aEdb6460ABAE82F5ED77aF1d5e9Fe6F701d8c4A": 0.000887279887748914, - "0x6B56fAecE16358B3e63b231837963465cB98A152": 0.001459143800064487, - "0x6B7d0041B1B05f1D8f86AE923Ec09557e32Aa416": 0.003073934112787674, - "0x6B8F4dC1D7D243a9f9b506D58020c866EB199885": 0.003176410682534911, - "0x6Bdb3A8ae008cE1d3073870c852010E089FE6753": 0.001872626148991244, - "0x6C9b8Ba06E2212D29561A5910f418a042fC788ac": 0.000273335624404536, - "0x6DeB5c18F9d75d5D8128F8F42cEB225dD234F960": 0.001627868877751568, - "0x6E99c76778B44b430d5dAc1559e7AA9DD76dDac3": 0.002352943406227767, - "0x6fDc3F38B32fF607199B7ba12459D741CA6f4357": 0.00251976638956371, - "0x6FeC2026e8E468825ED243445508f1bD1215059c": 0.001926101782739981, - "0x709e49864C46A307e8f383c6B0094062b74c6765": 0.000832106669875826, - "0x70a7EACE9F44F3C27832f92Cf5EFF9B7ee3Ed2D4": 0.00033741151530551, - "0x72CAb6D1Ee9676DA8956A7A8E74EcA4052d19696": 0.003437454405732068, - "0x72e1260FFa7e3e7F41eff646B24694F8c139c73d": 0.002110320098252279, - "0x73714FE3e21C09FaE810380c15C64b5628E5d904": 0.000498372346319018, - "0x73A5db333D383155D2E4fC506c2802B557108E51": 0.000230977753115089, - "0x73cDE0e4F0480EA6B98Bfa292Ea936685716af4D": 0.004182221756493842, - "0x73fcB73D180D013ae1dbE306DFcD59C5Ff01b66a": 0.000333931769184205, - "0x744c2f5FadbC305d20Fc91274b71a6896d294946": 0.002154405987584555, - "0x7460B763e92f58f58B80F6650B41F3d2cD10fC3a": 0.002068248961183268, - "0x74C9DCb37E9eFb795d4696212E8ae4c68C4d3D1D": 0.001223240999749143, - "0x75F223915302B9bA12eD8F5425f88b74379bE6aD": 0.001110282436521396, - "0x75F5607Fe0A27c57CCd7B1eD244Eee9499D68302": 0.000853395997600356, - "0x7643d5cA36aec928C15181F02A4263D9E1FF594B": 0.002011786909719163, - "0x7645e40EF215f9Bc44F384a0418c87024646e489": 0.002044342586676759, - "0x765C6299ead6a2fa713E0D323Ac6BDc96bEF214E": 0.0033278527113547, - "0x76bd993BD4A08FE154690095Ec0a3DBb51a0eb08": 0.004076238444491684, - "0x76cC155EEE2e97A34AC53e8b89fc44690Da753a0": 0.00240577975892889, - "0x76cc3f2Fb3f451BbEeD11bF9F64Bb35f43438829": 0.001990813064873342, - "0x76e0eEF2E4883f5163ACabBf1C00a8eb73D25d83": 0.004764401388187936, - "0x773B42430376334c327831C1AaB73f44A379F58f": 0.00038044383161311, - "0x78044a54e9009eEE6aba5A9418EA6380f153a7c5": 0.001874776999470425, - "0x78be141970C8378Ff7E14dc0E817Cb17b342F5e4": 0.000409374561948349, - "0x78d964e9629fD6104F8F13d0DEC2485Bc1a43A2d": 0.00120915164941758, - "0x792ed5735E87859792f96bE92E98360fd7c76084": 0.00056833064235356, - "0x7975ae9ACd918f2c2F77a365e9077d098A102C86": 0.001818905533266983, - "0x79c8039C0cfBDC3cdF8d66eFB1AD2836E698ea3c": 0.002745207218955531, - "0x79F7f0B17404756c405be60A60A491058C627958": 0.007808654191542071, - "0x7A75B62e21C490fe9a27A50a083D6a2b04c7fbbf": 0.00054190741796834, - "0x7ab3c28958844A758FFA564F09c73dDa7Ffc766d": 0.003062750855771312, - "0x7b56128FAB23816D4a7520Ef691e2607af97B01c": 0.00087502027835499, - "0x7BAa3b328603535006d76D7B80aF7260FD8A946a": 0.000450916094931589, - "0x7c05dE20A59b43c0Fe27eA1B85A2872E9EA519dE": 0.000297367085888908, - "0x7c9c7bB3D6880F0d720fEb4fA6164Bd3E49F76ED": 0.003325422172311954, - "0x7cA4b00a3aEc07F978D127E69bC16484a038619C": 0.00045013115069857, - "0x7ceb2a5C3395A5cfE09B66E7cEd496061301c316": 0.002232276676490786, - "0x7d822dd2320B0B079db5DFB0b87D63A0E9F090d4": 0.002860405156906349, - "0x7d8AEE804Bbad88d0081115Adc917F5d9bF6388C": 0.001899743234221034, - "0x7E1B249e6BAA2F60A87B14b43B1Ad731542bD9fF": 0.000700318590733549, - "0x7FafB471bad0589FaBa53769DD8d76c5d79aB720": 0.002629024243659779, - "0x80040d9c574156125E096d85AF6B6c86668d6CDF": 0.002222021358202793, - "0x803E38C54240244046545B421FfFE4e05BCD5D0B": 0.000403060462062888, - "0x81502de049CE028C2A91e9c91d059Ab8Da8Bf469": 0.005036699466795216, - "0x816a7FdeAA4B1Fd5CaCdD337d0A815347a5E714a": 0.001813361626403986, - "0x81864365b031c138Cb6a7c64526C7357fE4FFA2D": 0.001529874518478847, - "0x81B73F850A76D405bdd976Db6744D85c65fe9330": 0.003353245962229773, - "0x82074547555355BbE037e0E504d0D0C08EC4dBEA": 0.000563930998939954, - "0x83CDb49eBa3bC99AE57F5abE9c6cE9D601Ea744A": 0.0012501767793338, - "0x83f7321a05876f0bF973bEc3033858bb0b91e37f": 0.000253576097907972, - "0x841499f8F5F869c20886D581641DC181E9C6B672": 0.001789989869958947, - "0x84252729ed32fA0fa1b454b8f58B71758239d627": 0.002068626974566218, - "0x850BF360D7062257203854cEFc9A1629106d7a61": 0.000233865148295339, - "0x853E5f1A139FdEa47273A4632c70368d095070Cf": 0.001471304823364316, - "0x8578ffA6a6E9908B454CD38B93D3F11Ca8723A9A": 0.001898155682365782, - "0x8594E5a6f67cB13CF525EA15f2e1FaC3EeF63304": 0.002427596232541171, - "0x86CC5e1e8fb20102Fa7A0fa4afeAf1Cbe1BE273D": 0.000679366196250462, - "0x88330D5c152A3A064b8883ddE2A8a2aa3e4680fb": 0.004364686106772601, - "0x883Bb7134b7f5673b08fb8d3c31814B55bec3a43": 0.001391344852681121, - "0x8891E7796d54cF5b801F0A01966be79d7cC2a89A": 0.00231702783426477, - "0x8903349C5B3205Ceb9D004A051DB554f70D1Fc62": 0.002017975534804761, - "0x8a74781B294238d74f86B0cDfD4eE7b1dBE55d7D": 0.003417530192247443, - "0x8b1728Bb25502476d16CdCF0861669f68c91A9d4": 0.001247214210686356, - "0x8b992B29e691058a1EDD32378dc11E6480E0eE24": 0.001827176639363206, - "0x8bd7B5E860998607715Da42944cc9DE3486A3Ae2": 0.000699346289814744, - "0x8BE6B927c4F3aa56D9c0DCf1be363b0081Fe0BD4": 0.000376122121756596, - "0x8Cd66785F2A1B5ADc3Cc81177D485A8395Fce2f2": 0.000656200320462028, - "0x8Cf35646c42DA86292aBDCf64bd0f7e7fC644a1c": 0.001451440145564425, - "0x8Cf75F1D6974DB5215d81FBec287Ea8EEF35C95b": 0.000519927519621719, - "0x8d3450C45C789Cbb6E03baF1f939B8081ea41Ccd": 0.0018214506906328, - "0x8d47CD9B8b015B0F3865e8eE0b96b8125bb1F483": 0.002040355617210643, - "0x8dB0696b0835031ee2166F130d90Fd31EfacA4E3": 0.002653146287240826, - "0x8DE1cdCF6D3aCC777d08e2359Cd4D6Bc72e382a7": 0.000438739746115682, - "0x8E561b9823d9BF7067F5F64980aE26b6b9969e77": 0.003646453781237505, - "0x8F559d9F555131932345C2A9546df023c54E096F": 0.00098866912405153, - "0x90483C0d08A16058aB7Ec4455B8Be51a30Cc5043": 0.000588149937616228, - "0x90942873BEC9aA28a4957c1FF1C41fb3B8cf6a74": 0.00036617205785523, - "0x90b979c9E90EC5D5246dAE6BE32ACC451edD2464": 0.002100757033999859, - "0x90bd7028416753B38714F32acdE927aCBFD7D18B": 0.001889818145671654, - "0x910144b369ed067F8a2ea470ebCC2Fdb31c0dd9F": 0.002797157336750915, - "0x9247154eB39429505f75096d5A6be52acE076A81": 0.00135806585325456, - "0x929cB3CDB2C23fA479D72c21731C53822f5df881": 0.001448912903002483, - "0x92A5D7978E46759EDbAeF30012E4c60C8DEeE0A7": 0.0010956087692927, - "0x9301580990202CA724E2d2d3F2Cde88fF50735c1": 0.001684434109070633, - "0x935eFc16A75a6f0B59fa91CcD21Af633A117f97F": 0.00370337099812257, - "0x94478F8B27CeDD6177E238F48164A45245C854C1": 0.001102472607435183, - "0x94667C16eF36c34d6De71FfCE6E80C5d24672a41": 0.003389708729565961, - "0x948F052C6Ecb37aBf9f81b87c620Bb272E422155": 0.001326655632232697, - "0x94d0f3A10f88A63fcE0F2304ed63D3d166fdB313": 0.0020490265361758, - "0x95aFE39b111176629BA6eE5F2C1c86eF973226FC": 0.001674189479987855, - "0x967bE9835Ca02EDf7A8c7dfE26519763c1611277": 0.001796203191079962, - "0x96c00fDDa3f3129A55C0Bc9b48Ef504C3D5594e4": 0.00299180331265087, - "0x981387F73e94a173F9eE05a7906E299F99E23114": 0.004312837409283606, - "0x9860D7309039b9A44B1df878Ed4484133a881316": 0.002384094674163708, - "0x98EA9cC7128004b6b09D0fF7F922cCF51D6869CE": 0.000265932280527395, - "0x999EA3182C60ae6F58817C77Da6A769f6f731f34": 0.002049352587514968, - "0x99BcEa6bB0403927fB3c038163478D5b42082Fd9": 0.000874116431832116, - "0x9a0705ab1Cb8C5139171911cF0a689DA2F54830d": 0.000595677795656707, - "0x9a4773EeEE73e34e1EE0E9A64E4b7453b0b04246": 0.004769169014342945, - "0x9A4B6F0839637769e14DdFC03D4E7c537d8e25Bf": 0.002862973385887932, - "0x9b5d6a05E969f58438780d775C0037884526877f": 0.003168447002507213, - "0x9BC114CbDf47021f15416e720bC71b5341120E87": 0.000522280134489487, - "0x9Be6FcbF8d76201559627BaA8B0cD60cE7e06b0b": 0.001762480396329596, - "0x9c0bCC942E775cdff33c64906561A3d75d9D0B79": 0.000125010267582388, - "0x9C9A11a94f95cd31c06E0252eD0cE908b90FBc0C": 0.000317605393089572, - "0x9cDf01F751864333515c209B733501FA5bB14143": 0.001121291953792428, - "0x9CF0Ea03C7e23f2C466d48f6BfA14A85EF7CF4c8": 0.00054107608076499, - "0x9D3a7C178E38748a3a53BE600C922aD5fC45C0bf": 0.003126544705690538, - "0x9EFA7B040eDEC79662F0a7bacddE8bd1db50a8C5": 0.003506710586183753, - "0x9F9a6867d9Ed4630DAC6d3F9C125248600DF03BE": 0.001617015067675783, - "0x9fDB970aEF60007FeE4EA132B5f4EBc376740aEa": 0.003869483672880516, - "0xa02B48ce476ADe8A3f635857dCaF9475F79AD6EB": 0.001616189840039979, - "0xa1df756B063A867bfB3cf1fa611592Aa646bF4A8": 0.000705177083941647, - "0xa21cC0DE85E8c75bB10519872Dd3965ceC351e3A": 0.001173703038582787, - "0xa2E5Dbd496e25A194a11FC3e4Ad5AdA199e827F4": 0.000190120981281462, - "0xa31c2232842e631cCb2d2E4110B356Bab21E6020": 0.001806977094637775, - "0xA33c3B5Bd387B26F72E1c5e76bc1bb81e7935EE7": 0.002904722801428504, - "0xa33f0D43b87dDD418C029412b6dFcFA8a9C68074": 0.00034981925850061, - "0xA3625b1dCB1e99dCC1B9BEB6ceD0965FAF4e20e5": 0.00027416594484952, - "0xa3638f8044d928b42dD74085284bED980b0e0278": 0.001489714764094299, - "0xa3651cadfc97186D5B93A0aD7Ea32C126a794BFF": 0.002467720955045497, - "0xa394d3bD4416380cC3498af7d764fe1Cf76A69C2": 0.001963537059139433, - "0xa3C18bAe51Dfd07FA152492d685c457D0fEE09D7": 0.002029954724613294, - "0xA40ee0717533dE5b87D6f2054AEE815B8461126a": 0.001482451760135974, - "0xA432B3e56A6F4dA4574cDF2f27bea9bbb5543011": 0.000741758386152588, - "0xA4635d0D583F6A5335Aa3CE39CA7D7c2e7a7D01C": 0.001081951101240274, - "0xa4bA32A41A317b970c4ADFE1e1573930c2B4551F": 0.001101759684429442, - "0xa4c8e8D8983e53381b25967659A368f8E108aca2": 0.001392081305519205, - "0xa5D2817A0d9547af625942E6F3a3bEF71E5f5Dae": 0.002463406117634708, - "0xA65EE589b0353e7cd63c03FD534bEa61C748c3c6": 0.003122326719810565, - "0xA6A162FA210411Ef494feAAD1605c415f8fe0da6": 0.002876036318224835, - "0xa7A56D141C552cfB45b4AF6aBFF0aB76f9369c28": 0.00287960685857875, - "0xA7e781E2EA7740177d9b9E13Dd2134A103f5833b": 0.001707803355211447, - "0xa85160a81da205AE57F6d55F16C9C43d773c7438": 0.000328418143729698, - "0xA89fFd4063866481f3DA231bc2cCf88Def15b642": 0.002201741825983557, - "0xa8AD81A7f78a55E02f6267F2568e96445fa2A469": 0.002754570288532948, - "0xa8B8f0B17Ed13a3663A8E3f169C42464aDddB984": 0.002547112551875254, - "0xA8E20D1B16c2821c2E17A58eB9c92c2ec7699283": 0.001759062914952147, - "0xA941ADc6DC04b0cfd17Ffa75329B680C9A1B3eEF": 0.001822412558997712, - "0xaA8eacF97AF9Bf3eB4cBB76E975a5D6aaA220606": 0.000364739785325574, - "0xAAfA1bF92688084C3446fDC741c1453379cD72df": 0.001078139579160549, - "0xaB0Ea94509caa5703362EAaFd8087d205f97a340": 0.001233541625572076, - "0xabe5B6e8a4e79e7F27DB3a6d9E6A6f05e521f604": 0.002119653671187518, - "0xac2c2C3fd735c5DB2aB77D8358DaeE705932ff3C": 0.001378735155214537, - "0xaC880a2568c6F5719AD59C8Ea3BC11a910775757": 0.003592688241339687, - "0xaCB4FA704c4A7092B3373D5c57443ed3261fDD18": 0.003630255800827459, - "0xaD82CC9A78F2cf917E56e6305A01424b9107EC43": 0.000907934643521791, - "0xaDE8502eC7a7Cfe5fc273cE3B94736BB1F76118A": 0.003916966524232559, - "0xadEF6E3234cA45D5bc3C2bdDD4bF427862c60335": 0.00102697588125076, - "0xaEd91598B3ad7e4b6Edc0fC2a0D9E16e8D58981b": 0.002529784784036854, - "0xAEf6a3580A365c524A5bC9aabeB2a13c2A1a7B7c": 0.00436429371858028, - "0xaF4C815CF13Bc8671a2a12BdE62aABEC24651ccC": 0.007448462468293356, - "0xaFD255f71cEBa0c0EceE10fa52F3e2fbeCcE95C4": 0.002017913554351507, - "0xb020747D162105158f31bB6Fc0B6DfAa66B23EE9": 0.003081457554423888, - "0xb187ba422872C0467390155826e5290Fcc9fa3Df": 0.000669892488329972, - "0xB21bE96Dc75717272402eF97A5CC144544263E3c": 0.007989764775625071, - "0xb2a275B464EdcF73c70EfdA20a5Ba5f742470D4e": 0.00080688572111893, - "0xb36268588ED030B4d8FbB22a0B4ECbad1194e683": 0.003581681129386093, - "0xb397dEe549E3FDF24C82b72707cb6FcD849d214f": 0.001127914464566378, - "0xB3983fd5997711935dC61118e684DDCA1CE3F8C7": 0.000298691331723346, - "0xb4C907afdA8C362B58281B5c43A2e7b79f089D09": 0.00043259757817898, - "0xB538544c0d0971dc6cdcc17a1Ac50A02bc0A8B0F": 0.001446947123780433, - "0xb67a6E67072025C1db86e552dc17f7Bf9C296122": 0.003520536193415728, - "0xB6e74e6fD559f9207679D128ddDBb35B9042A166": 0.001782015073476024, - "0xB73812cCE6F5cB7ada40A134b4b16AefbDbB9472": 0.000335504749350614, - "0xB87000FF076e59EBBfD973008Dd21941Ff9D13b1": 0.004408962239023198, - "0xb87087bE41D0299e31ee8c274540a8bf15bdc1DC": 0.002544955155700901, - "0xB8B5caDA2A1Ab13f421870555F99887e3d6A2e77": 0.001861507909183529, - "0xB8C8D5Ca07C82e7E4c73f0cE93E2a7dD08956cb2": 0.000566355500311814, - "0xb916A83cC28F6f63ca9807AD3bFa84d9e14DF963": 0.002088068889187287, - "0xb93EFD0e79b769D2b3Df7aa64d89F983D2fd02FC": 0.000337327081910856, - "0xB9F187188A9cBF21b204F125Dc116a997fC29aE9": 0.000270307464448756, - "0xBA93f72e240d7F45DB22EbF126c2D87dDE238918": 0.000760381014311528, - "0xBB323229972D001bbF725b3fB3734eE53B7455CC": 0.00041913220343746, - "0xbB6aDdBC9C95100792Fd80FEE1cfB46881DE84b7": 0.001306095906016642, - "0xbc45a7315eda040A0e0a53E022b62042a71077D4": 0.000287544605221634, - "0xBC46980A01D8301D336fbf9377aAe711d34fF122": 0.001833265197573606, - "0xBE71d84a622010A0C9709a443017FA53419706f5": 0.002003770387416666, - "0xBe815fD2CBF30D07b804d643FbEEd27b8E663acB": 0.001385352508463922, - "0xbe8bD46D8847a8319261F6Fa137156671dF68982": 0.000230976636674221, - "0xbf72eE28dc8627AD3e76bdA841247EB39837806F": 0.001899623293470812, - "0xBFBcD879dd913255B32100a72A581C963e7b0ADC": 0.000299029647509498, - "0xC0867A1D3deAd93c0E79Ea3fD54422671BaAbF37": 0.000256529672672097, - "0xC0AAbA6E0dD2Ca4C2BE7Df446C121C3E6118bdD2": 0.000930044726786784, - "0xC0Afc9BaEcE062D4cDbbb56eFBe33BBd827e560d": 0.00129605226073346, - "0xc0c13E73641080b8a890261b731f9872cD0bC9d4": 0.000117110196735569, - "0xc0Dc4010e76fbD53C82b19f8f8d7604e37289fB4": 0.0005085470286171, - "0xc0FdAbeF949f28332f596e66eE8e06a13A103c02": 0.002197195124105275, - "0xC3Ac3355B2686Fa503246a92e34D0B7261b39d6B": 0.004108176013136093, - "0xC41A3d9ED9DD925fB057b7C1599249CDB4C6B66b": 0.001776535432640127, - "0xc42851d834037cA1f82668596233DcA69654867C": 0.000558941540925206, - "0xc477F54B5ABBc255f366aC54FD924a896da5e6a3": 0.001327406402168072, - "0xC4E70E97A54bbf4f9796099282fA47397da4b4D9": 0.000665931259830168, - "0xc56d5742F3DcfB9Ee9aCBf8d86385B61b1F0bB33": 0.000733689799816614, - "0xC573dDc59824F248D3688DF0474805F35C2C09c1": 0.003429880143140206, - "0xC590314dE55b52C96eb34eDbC4b55cf8Fc8cD510": 0.000468622920904, - "0xC5b1624c0aFad0E366A9cDF80C08C3ff8253710e": 0.000716488718332234, - "0xC5c90045A5D097625634C7d4bb7dBfBb8E3310AB": 0.002151916154445083, - "0xC5E789964681a9ACf7D8C84EE89252Ad531E6C8C": 0.00209505471583887, - "0xC636DA66cfa5c363C4785835069dcAF85ab91feB": 0.001650890862846228, - "0xc73f65Ea9d3d3c165cC6Bf31dE607cb946B1e4C6": 0.002086677225362585, - "0xC84FAc7D2F80D70b21A536Fdc1Fde5cb404d747B": 0.00706528481413282, - "0xC8a4C0aA604f225aA006835672CCb68e661f7Dbe": 0.001023872103175712, - "0xC8d23C39c8F808D599b65D4C9eED01B8580a66bE": 0.001660993596091826, - "0xC92b2aF1B472D39275181f502b9d369ad9507DbF": 0.00021049570852914, - "0xc92f8051ae3786fe90CA5aB89361DAD6730c4Eee": 0.001914942211312756, - "0xc9B1B3Ad7546703a9AcfE2940287ae7F9CCAAB70": 0.002884264749883987, - "0xca30cE2505F78e7B4f07b2d0A0F22eD62B19051B": 0.003023154432565645, - "0xca49ed45A7d23193b0Bd2BE322D4F0C63168b34c": 0.003175292204874449, - "0xCB4bB9D616f27dc84a256b768B4C393fA8010caa": 0.000384449569462733, - "0xcB4E72E300390B3E352f20787300CB741fCDE09E": 0.001485087259569859, - "0xCb8c77837f470053F91E1e288CAc223118C69937": 0.000520092891168132, - "0xCc50808A98AB15312361ab4837f412B2d9cDdA38": 0.002129457522390259, - "0xcD6DbaC9cFd5b348744640D8ceF05f1B5245e2E0": 0.002589611500333746, - "0xCD779f2e141fbA5A332A8Ae7882Cb1aD86cB8D34": 0.002958572598237754, - "0xCda9C44C18c5C83963aeb1681fc4198542650345": 0.000899944832054884, - "0xcF2e28E5E57461254B8B254AE6D03c89d19BF743": 0.000612845037124201, - "0xCfc1D59675355d5288C982d23caF28a2D0A6d48e": 0.0021166793112989, - "0xD02524BEeFd5164Eb28C77CD3eb2C7De887B891C": 0.00072549399647567, - "0xd04383c1e5Cc572BDBebBB88a1292F9aCe70007E": 0.000875459348520922, - "0xD05F0F552d72947b471a4C4BEE98F9207E889482": 0.000357507395322018, - "0xd0A530121747B005af6Bed69426092cB525713d5": 0.002258230098316503, - "0xd17EB770E4E209C186cEDA0d7E09bFC03D792b36": 0.007854743410674207, - "0xd1Cd2FD35C63e27A33f0b5ECf9C92ba1AB9c6dF1": 0.00046190163348943, - "0xD225626025F48Cd43cb35CE935a4F4B856AEd21b": 0.000617205280198213, - "0xD25f7e77386F9f797b64E878A3D060956de99163": 0.006008179777689715, - "0xD27122760634f46994815A2B5097FFF7b0e910D5": 0.001450915497136981, - "0xd273f87e43851Fa7f0518E3B385c0d964621E3c6": 0.000544471694479184, - "0xd2Ad096Ed0757dc4954f66765dea737e5a687dfF": 0.001742186993010333, - "0xd48010De315e10D071853b1466f0C273e766FA07": 0.002784464923297565, - "0xd5769DCBa4D94716e860431Be65c0c84C379fFD3": 0.001324700945656694, - "0xD593f878270b61e64fa65dAA06728D0bA89C792A": 0.000820867618037016, - "0xd5E10116D747EFC7028fac192093D2AA2Ba9EF12": 0.001676456834983982, - "0xd65e71C781BDd00221eB77B920298663D0b83484": 0.002211278863920194, - "0xD6CCf8Be80aa6ae4320AB4D6551C6f3ef96AF7aD": 0.000486618749418646, - "0xd706bf4bb1560a73790D91B8fd585Cb5508db6ea": 0.002308707028848392, - "0xD7D00580798FA514bbe9b71F3B84209f83Ad5bE9": 0.001984546563744876, - "0xD8C3cd1A7576efC723357B7158318f0CeE0e30F6": 0.00044068200908034, - "0xD8c50C68066eFE49bC12658A5D7C984E7254D417": 0.003099888050457143, - "0xd957f2298bEFD78E946643602fe04509f45Bd5bA": 0.000230977753115089, - "0xd9e352554D0e4269d9B158d1baFC7975fd4d402C": 0.000760604591941388, - "0xDA6De31eB28a648884247708385a0B8027E6C4b3": 0.000790580459432837, - "0xdAe56179CbaDA38DB0A15da62D43Dc66306f746B": 0.002320295461415382, - "0xdB040b1bAD2941e02F6fea3a7f4a13D189E0beC4": 0.002004344134765031, - "0xDb6D77A78b4da7286E3C1A6828EB83D9F0cCA527": 0.001093054549561128, - "0xDbD9416f32c409b3c7A29655AA515bd717616470": 0.00325733870134353, - "0xDcb26b5dBB5F8798C1b434597ffa5e4aEca20d05": 0.000800468300315379, - "0xDcdc4E48c3DA83109322E3fC507181D65687Ef84": 0.001603467669571091, - "0xdCe31D9b0a5B0E2A40fcdf9A2ad73C3CE2071C15": 0.003834170421679551, - "0xDCFCAEa66D61Ac1B52bcFB647c03f56c0bbCAa28": 0.000511457002624332, - "0xdD2CB8c9b8FCCDc366AE60f4FE1c99813Ec0d18e": 0.00832967187464946, - "0xdd877AE95f4aD48b4Dc640F52E802BcBE3301130": 0.002270430581135096, - "0xdE7250D923299e1EcEDc0743b159E95B945082d9": 0.000434934982653018, - "0xDEf3560E74E9569d32339337D6A05f3F329D7a3a": 0.002032296297916199, - "0xdf9Bd257d55271851b8F75613542635Fc608CFc2": 0.002101255931292738, - "0xE08A026bAaC28a95041DB74Ba78CE93Fb6aC766b": 0.000538361162153996, - "0xe0b343b462aB6D0d3048644D1a85f287D46FC23d": 0.002914688519788281, - "0xe14B7Bcb3A2A9b2EeA0a53dCE0A60F1649660C4e": 0.000266237354997955, - "0xe1810961A12B5B38468fFc32aF3b5F8dA1EFdB53": 0.000446224064526624, - "0xE19243a27D28a8Aebf138DeaE361b8AB53862a9F": 0.003641340331583464, - "0xE1d4C898E9720979c898e0962a1d8e3A897f9263": 0.001372531944753518, - "0xe251B115E89036C0bc0a8Ff09B36f77ef6291D84": 0.001264864072616305, - "0xe2A2f2A338EB923454e331422e9b6ef872325Bb5": 0.000843577679845794, - "0xe2A85879BE19fF727cDB79Bbee733b616e7c338d": 0.001377601143189636, - "0xE30C4Bffc186667d5dA5EEfB505B419432c62168": 0.001840082632911276, - "0xe35c3f0ad5972eC28773b31598527a9A0D0B22a6": 0.007238533487009321, - "0xe36b79317a75b08384c33D21197c7e3273886873": 0.001227236915685986, - "0xe57fe5bbDc76E8Af1448550cA56e7E36c8Fc8272": 0.000241820836428222, - "0xE5E7EB7B5E89866A6D852F55BFE363EFd50D2F19": 0.003478915545574645, - "0xe619ea101759B9D0c5dDC36b59f1F5e55FEB76B9": 0.002359796399082513, - "0xe63757E3cD485C9b35b3a972fFFA2d91B8649483": 0.000986735864247628, - "0xe67d3b0BDfd1D853FBcE6C0898b464e332a67B18": 0.001198794239274962, - "0xe6b5A31d8bb53D2C769864aC137fe25F4989f1fd": 0.000753074201404674, - "0xe79464c19fe30E6Db25A74aECf65AABeb92A44dC": 0.00163463112987963, - "0xE7Ff7aD54492A38AfB99bb5d8B897C5f93A66f47": 0.000643100129523618, - "0xE82C23a1084a4fB27ED46628c40301c0f63F0C40": 0.001196899433264345, - "0xE86A48bC1D340Bc524d5529222F5b51995bb8132": 0.002739279128097161, - "0xe98ED74D2AEd7b818FA01A839715A917D1341bC5": 0.001032817481176946, - "0xea03Af40FA59Ac9C311187Da0f9b979DA073C226": 0.001978266469119038, - "0xEBac3e24c3f59d50a713F2c79535acd381487486": 0.001976383990070969, - "0xeC2Bae309d0A18D7dDfD4EA0f17a2f60817f4E9c": 0.000645933072947126, - "0xEC67006aC513BF20ac599B48f1f9F725C142BB23": 0.000722736064090086, - "0xeeD671a75689E7aFda9F658c8482B0939bEE2d34": 0.000233600555683327, - "0xEEEba9f78590f8C05c67b627BB67bAF22Ad9597E": 0.00027391236297332, - "0xeF7220723E580F03A8f8b076Ee8623b1dF0103fa": 0.001441243816484446, - "0xF055cbe9B6b30D64AC1D7305cde7BA6c0993C86a": 0.005628685590980622, - "0xf0b7e13a31eC9D21c05fcD91f71CB82498864D5F": 0.001361374639710291, - "0xF0D9A0C82dCdE0675E2E796f6e25E8aec3e52f12": 0.000877071736336323, - "0xF1De794eCF521Ed64bDd4DD55308361511f87990": 0.003713800514850269, - "0xf2009F3E705e48cD9E1d29397fc19Fd7E4870cBF": 0.001693162005814965, - "0xf20737e48160A87Dc9D1B26D8B63C796d2F1EA91": 0.007088051537280779, - "0xF3579d18e82E8A1353D58D1B5a7265F4f5844A9c": 0.002003183311098456, - "0xF39695c39EaCdf81D146cE6667E81476Ea9b3fa7": 0.002222254263173393, - "0xF3C162C189341D024ee753223101612ABF6fCf9c": 0.000982476308149558, - "0xF45E1A95ABCa5362844634106a1B0705CcCcfA23": 0.00181078691486248, - "0xf5bE8850b5758acCaD467dA86119Db517b8CDe0f": 0.001529318310414164, - "0xF5C14eE163B349ccC50eBe31500078f745500580": 0.001221438452773522, - "0xf5DF7a18dF35dA5EcFff6D55bcF920e3d8F6d5Ae": 0.003188873408831, - "0xf611B9A9F0d9a0DF279665b05fE338b29d53744a": 0.000904891143724273, - "0xF7FCAfb56130a2e39bD28e5115E90E6972b83e5a": 0.00174590331797519, - "0xf882F94D9fA5a7bb883D3Dfa04e5A43Fa057C333": 0.002919695715752449, - "0xf8C9a3f1E55b9a91E413A8C8bB9F5f84C6d246cB": 0.001487950376516927, - "0xF9D3A0a21eca45C45F9F476Bb4Cb40c1C4f3aF07": 0.002179385491415533, - "0xfA8cE8D44271201e9Ce37838ccb75BA482d597F6": 0.00110276420745576, - "0xFa93E76Bb7de1071D6f9C0f77Af883c2a944B2d1": 0.00078487359042108, - "0xfAEF14B594cae1666846daB2780E964df8557950": 0.001783208136309095, - "0xfb043BBaF380A06c01750ce0a6324e38eD11110c": 0.000604414447549389, - "0xFB364E4D8eF3bf2551550DF01e0c8d55D3A772EB": 0.000958832180440529, - "0xfb4d1d353f95e477235611ed67076E61643B5614": 0.002094968733111619, - "0xFC2ed2462f05608b6a21cf1A43bf24a6Ea08c4CD": 0.001852574099363942, - "0xFcECa6193031F7f1336Fa055edFe96555644Dce8": 0.002026048122277744, - "0xfCfA494c13409172109f161C428499B39682fFa4": 0.001918027966172223, - "0xFd0Be09AAADaAb67523e8c6a9A3c1D657aCB2B5A": 0.00457870320961811, - "0xfD8355b24aB8815cA2d76d1E495DC29B4330241f": 0.002577673853038057, - "0xFEAB4fFA81BCd17dFdC2d7e906662527697915d4": 0.000369892464405737, - "0xFec5287823f5a317AB879eF8F8901Ad21c7D915c": 0.003531197597318023, - "0xFfdBD837ADAe8558684111d4B5cf9Ca36F58569f": 0.002119049556324283 + "0x000000000000f8E4fE2a98574fa81C728e340764": "0.001623200791717199", + "0x0013Fec13D8e4bd86AF7a988087B697ca1057B88": "0.002070984318620129", + "0x0024A67e0b91131d6978e1e0f72c94497bDBCc35": "0.001982718698536916", + "0x005CDb3B0B0964569ce0aCbEF483443296cE704B": "0.002337951423375661", + "0x00B64e31a3C6f59b2120b50b8741584f024722C7": "0.002629035364475586", + "0x00C3C106D11322c7aafECBF248cEE710ae3f0a5B": "0.000597858515100745", + "0x00D71C4FA96e518dD54E459114408e7aF9297C15": "0.002392552700169229", + "0x00dd323d8f4bDcEa52EDBdE935C1ee97C009c5a7": "0.00030078413245808", + "0x00Dd84F50e5699aA9F1a9f4f52c428BB305189be": "0.002254650304625379", + "0x02153ebE18bc66C57E540423E69A881a70823d40": "0.002618388898398077", + "0x04AD0F62A66bf8FfF774676a792E88D10942e2A5": "0.002084882404298553", + "0x05C6A4dA04bE965B659aF1365314bCade309bB82": "0.00124088623202724", + "0x05ef6560a7c9C2951B35AFea0868382487e9B77F": "0.001449839720952172", + "0x06Ce05Db7D0A4539B3eC2fa6b81DFe11a32120eA": "0.00213402154104884", + "0x0724CFd1B40f56B506136D5A89EedDda31deA725": "0.000435114378111624", + "0x074F2CCfB2716fC8B6aC579173f1aAeB1f759d52": "0.002251043091099571", + "0x078352359cBd47652b6aF7dC1c46DA5Ad1378035": "0.002534179075446767", + "0x0788f0420961aE4806fc4Cba0898A9ca0300eFC0": "0.001227657140494814", + "0x07f88CeD359895Ef9CE4b3A09746954e7eDFf139": "0.001343042563385011", + "0x083083Dc8dE34B1dB09910ebC8a8Ff7a47C546ce": "0.002725193807169186", + "0x08610322dfDa1dd2D129b647e13840e832D485e7": "0.000357972841447646", + "0x088887cCa9F1E0a6a4D42BcBD3e107686bda2486": "0.000670860511931726", + "0x0894f897CE9b108cDB97C239e4f96C407a248e92": "0.003149757188583824", + "0x089773A760FEE0F1A3D3ECfADf4b2E145FD1E88f": "0.00169629330901413", + "0x0914Bf3e3DB541a79f6587F83A921Eaa368CAeA3": "0.001110997322694742", + "0x094DB477152D5678A0cE5e263C284DFf1052700a": "0.001250099351514977", + "0x094F5F0706DB7e3715a87Bc37437f2E6e6029B3c": "0.00056259881232371", + "0x099aF188E9c68B91617EfE4b09Ee8CD90ba4c63d": "0.001958173934655549", + "0x09a10823b87Aed0A3c348C0a20d69d3276192913": "0.00106930717885286", + "0x09C1579AAE05524f455AC4852d60C3e973ad0715": "0.00328306669870331", + "0x09cD0D28125587e39a29CF25Ea3f7851C585738f": "0.000532900234024956", + "0x0Ab373B6D140dCF3919E17D277Ad1Cb818B1EA53": "0.000598416251823648", + "0x0b0221d279026aC38eec4e13408BA7966Afb9FEe": "0.001701370489208542", + "0x0CB8dA6C265a90B3CCE8431267c0A94a7f1db875": "0.005838128588386673", + "0x0dD7762E2fe09c9eE2F5aCdeA19C102f7c16D8C2": "0.001237634310364501", + "0x0dFb17299E2b39C63602Ee11BdDf9688Bb66449C": "0.001491818707670364", + "0x0E054B1F4b103A1C92866B3205EcF818334caCf0": "0.000265937422231955", + "0x0f8fe8e8B7Ad38615904a08e821E875fa19d8b67": "0.0039965363551254", + "0x0FaD7Fcb19f3EBe9402BF0623d7ed0FC4F1dEf15": "0.003798075899170629", + "0x0Fb0e2fF6739060A811190b94b6D7da786735be0": "0.001649341817605003", + "0x1098874e7b4435615CAae49AF275B22e195A574f": "0.004958508195265784", + "0x10D6F9Fee0d48E7db7279AE0139cb5b577bB5516": "0.002686585110209063", + "0x114D4348265E8302980e7BA2db441FBF09EC3303": "0.001605566072098302", + "0x126db3213b309A8D554594e591e614425cCaC78e": "0.00210489624540066", + "0x12abC23621Bc6a6217c8190Efc21Bce9e0cad459": "0.002036727767680347", + "0x132DA096d35f9DeA0FD7F348232582DA4e551dA0": "0.001911522861608885", + "0x1379D42CC081790d6205712b79f6E133d798af81": "0.000929662792426936", + "0x15856FdCA72b0429E6E2117b7675dC2b0E6272a7": "0.002142293956414096", + "0x16D12711626310b5894783ca187BdAfe7aa4597A": "0.001347869592891393", + "0x17e2eA46935588BcE435278Dfc4Ffb31F8039BcE": "0.003101468775876044", + "0x18fEe6e511646B8ea2e4964277574F637Bc03f3b": "0.002979943874029252", + "0x1B0848A69E665eEBA88bb877b67145789d3d8b61": "0.00294200765490773", + "0x1bA4b6B2e5864838ed336495eCE7f456b1ba1FBB": "0.000271516145173994", + "0x1Cd79a62361Ff4AE9CFefdc128A255B1495627Cb": "0.001094860335258598", + "0x1CEe194Da1eEfe344fb2e7f46faB7D3A65C078e5": "0.000554433439102433", + "0x1D1C0E8394e6619Bf75C0F2e9321B3D324409283": "0.00234538028077862", + "0x1D463047F4c954D70d2718AdF96c43f24aC19dEe": "0.002720351640606777", + "0x1D98cAEFaB4bb543d98Ec6136E1498c34AF32c85": "0.000905622562308438", + "0x1DE746BB64222C304b38F84613745323cB6C7fC1": "0.007710366790600202", + "0x1E1486d4c30fA85E7fD5AD87cC7DcA15a626374D": "0.001704259387520791", + "0x1EdB50d83f76382480886597A3023fC318B2ca66": "0.000480554189311596", + "0x1f12254be217Cf9E9BE46960c36970390b07f16E": "0.000564319584213034", + "0x1f63E3125AE5b76240954F78dF62b4684CD88c25": "0.001171153912008066", + "0x1FA1C17dc5dAA02730b97B7a9b9D75710244d98e": "0.001403209286460627", + "0x20271eC8650e0990201EC5c785a5f3E8b51850ff": "0.004044210483401355", + "0x203F9674bE9782BC4B194625Ee9dC6800e65B2D8": "0.001117684671989674", + "0x205a89902311Bb2c44668d5712D7a21781279150": "0.001085309373654446", + "0x20A0fAb3e883852228dC2D54f4fCd4ceB6b6cd68": "0.003650632091718417", + "0x2108a6d1f32D1A932431d64E3328D1d45bD0520f": "0.006374040071022786", + "0x212df1ED15FB55607f180b8E26dA4A3db66b04d8": "0.001398354506323405", + "0x21681B5fac7Db2d8DD027487FeA9cd28B5c192A9": "0.00425641869693439", + "0x216bf62B05246bf4a1694061E8769464A6BFD812": "0.000584902357161496", + "0x21a27324B609e864882778c703FFc42Cc05daC40": "0.001894091978422001", + "0x22992D673Bacd1a43508294fc00597158a6B5816": "0.000340594444861752", + "0x22B95B36a3f4a7dC952765f9CC110ab455Ff6E4D": "0.003513543769493914", + "0x2352E748C9C090f44a8418f74457554CCe8D0485": "0.007120473344033869", + "0x239a01C50406Cd2d5943B408b49b32226741E1CB": "0.001367521023877095", + "0x240d2243D90E8968D0c8E807202bC8a2DE0dC53C": "0.000230780779968753", + "0x24eb1c355C05439819a23DD0842D5D038d1CA05A": "0.004296183001431525", + "0x24F16D0Cda8c2De21c762E0295C28d7249a972A4": "0.00309793217410008", + "0x260D417fBD1716B1375CD311f8a6677c4a780B3A": "0.00214937623772284", + "0x26fd27a26a6C1EdE36214512ee4E56440a0cEbF5": "0.000470793957213322", + "0x27064Cc4FE5bd5a20d0e5A21390a45F5a44Bf7D3": "0.010849346915887568", + "0x27459423cc0f816D965A97dCB90fa45774a18C3A": "0.000750370507871038", + "0x27b7A1b3c4A872FB30cF22e8716596a2312CFD2d": "0.001857557792118634", + "0x28cCfB369Fb97929068Cd30A390D37fee0037C61": "0.000573788814505132", + "0x28eC3b46262c614df6D5A3FF2726c9746F1d1675": "0.001541893574210529", + "0x295c5B0C1D5acEa1A94eDcd67005aec356ad1c7E": "0.001808342328838047", + "0x2a9437DE0cCD4FD7b7D98831213AcedeFC7a1092": "0.001902006430166225", + "0x2b379bFb86e900fE8f3A1434ee79097Aa5b883dc": "0.004023124829165172", + "0x2c26767989D49215d249e6D36F8e3FE2717f7DBd": "0.000046626720589143", + "0x2C281042A8dc2699e4e2BcDac11c2810dd40d8Ff": "0.001671269695907393", + "0x2C492138498165C3f6fF94Ab7d0B7Ab6dD546AdA": "0.001042570356273628", + "0x2d14a06687629C8e0F9fcb985814FcFfb60FD36F": "0.002804508864017687", + "0x2D29986ad59F77676c204d09b44Cd8Fc9EE7B6a2": "0.003084938156140876", + "0x2dB601b85292C8c94E87BAc3e56B3fD19CA45063": "0.001955301462889607", + "0x2EA989edfCac6531cd912d09A456f9809BaA5377": "0.001248519426706471", + "0x2EC20e5aA17F736060356f6B186208D5Ce0aB4b4": "0.000401416864313636", + "0x2f55877D6D8A42BD87e0325201cD15d63aBf5866": "0.000522007119886494", + "0x2f8320C2Dc28681Aa5BBF92e79C37BE656a7D5F1": "0.002442970611304262", + "0x2F966072f36109F27539E5EdEfA741912206E491": "0.001030197369633942", + "0x2fbbA6606C7628b749C6814fBAc1f88fEB21aeFd": "0.002728062359897463", + "0x3009e81f3b145c71A409313306Babb0AcC219aDb": "0.001007745932840434", + "0x3081508f0cD453Dc99Bbda26ab35Edcd785cdd88": "0.000535939904748932", + "0x30b2DAEb3757B6C7462cd0D776828F8d7398BE50": "0.002955698206664348", + "0x314FDb3cE492ee03a0eb037De01Ef53757C73936": "0.000773119450595252", + "0x31C44F5af149d2C9374f6A4d7253d0Fd69b127C9": "0.001039654649858049", + "0x32006a2557954336E877Db126A25e4ac27897C86": "0.002001533622567478", + "0x32a27a34B002aDE54C21515f77593E2086f5E7d0": "0.001904149153193711", + "0x336701baB9Ee6a829a5d610A301E978ACed202C4": "0.00105201937374925", + "0x336B9DE28D67D692C31DF93A9b8630B2Fa50d88f": "0.002417887862933094", + "0x33dfc8Dc28853A4f9FC0ec04BB2B67C6379CcA7f": "0.000609674711855852", + "0x340B8E5B52619c0ade021F806348e11274783740": "0.001392412572417687", + "0x342F40FC637e631f669a5b38fA4fc94Dcdd7DBED": "0.001285220148936264", + "0x345B46fCF8E503AE3b89174a59C04D2D212A5a10": "0.001982372603469258", + "0x35A7f9DB799649908688826E06CA754Ea0153724": "0.004068294499964118", + "0x36Ba943373FdE856457511ef8E8955323174331c": "0.001304975240793567", + "0x36Ce63c738971B948Cf0Afb842b7617254C15BC0": "0.004321177405122993", + "0x379570ffA1A60790A8B5955cf643F868D6ad4c9E": "0.000531220997599391", + "0x37b9171eF596Ac6A57c1d2598D71345e2206A5E3": "0.001944819017097703", + "0x3800Ebf79fE712781916EDBeDb169bA295dce5fc": "0.00080065779667571", + "0x3895799b03759423C728Eed3aa0C0414F5179f79": "0.00103015959453971", + "0x38F855e64542641f9e254f6e527351b55b560C0e": "0.000707484196836413", + "0x393950505b160607F40D11AB956C9406DBe6e4ce": "0.001439077395382837", + "0x39ad454BAD7d4909137cDAF1193cC847eFA959AC": "0.000998226306326582", + "0x3A4a969169aEbAb4e9AC667C9aAC62DC54c53A1b": "0.001661521763325315", + "0x3AbEBE2bFd423dbb6357674476D44E9bD178817d": "0.002273991452265629", + "0x3b59d6B33E8F8dDF9734917a40056D07548a4444": "0.001128045778703466", + "0x3B7236C911F87fD75315c4Ed44A1D2EEd725Ad14": "0.004678752876715251", + "0x3b84E3FFBe845c0349E258f243B5F00cA22Ba587": "0.000404368233109516", + "0x3b9fFD4CeFFd768DF16d79e7492A1BFfD087C44f": "0.001969189304064087", + "0x3bcD8de636cEa72178D8f1285f5Af0dd02d0B142": "0.001867467103399945", + "0x3Bd0cbC96186Cc3eafB304111e6Ad20a4Ac92F8E": "0.000431880615588246", + "0x3c56D7BB7b81282a369920F4816D75eFfc549b33": "0.000212558777040274", + "0x3D65eD138686e2AD54006d4Db83aD4597D645370": "0.004183334831553569", + "0x3Dc3862Ba073D508e421671c7F44e9Ee5d6B33CE": "0.001686882027902168", + "0x3e1B1A4a8fbA26E80F4678d3eA3AC1DAcA78523e": "0.003125073719379432", + "0x3E59864442ff8e0043b5360Cb134F6Ca2d514152": "0.001862838207470264", + "0x3F180F32AeD8C10Ce46065e05185Abc69F1D70B8": "0.003428894356078606", + "0x3FB7d3E1212cee588b14E57aE9A50eD93eCa0580": "0.001483608671467378", + "0x4010650464cc07e447ae10d3135F8c82554b2528": "0.000534635647165048", + "0x402bED71F1B26a068664C12818ed721E37155A44": "0.001992875732155986", + "0x40602DCAfbeBb5635ede96B2EcB94d534fcB4670": "0.001130821318515792", + "0x40bFe49745Df251fA0Ac7a3f983101FF170c389b": "0.000451794451432436", + "0x40fE8993df6f3915540aCE94E3a3d86a48829664": "0.000563271918036863", + "0x410fCF90a3805DFba3939827b0E75bD5fc2ef8B3": "0.003074690002145242", + "0x415106767827A7856D826458a486a87e0e15097C": "0.000452424928595454", + "0x419d955a9C3dF6A1b9eB3EbF2d21a3C63A8d57ef": "0.00400654081690959", + "0x41a1F47F710841F2f4cf492149C205725875f400": "0.002325962715286745", + "0x41DeB171107fBdBb7290eB4a8E77142c4636C13A": "0.001894591765754071", + "0x422Db8FD3778343B595762417b62474919eFeD41": "0.0019755448305781", + "0x4241A9998720cacB5902cF887A5323Bb316E3166": "0.0008062558287423", + "0x4241b7A1b190F97213cc092237833305af62f563": "0.001076317288004069", + "0x4289C656B76B20eBF1B5Fa4363dA812346919bdC": "0.001136506580316892", + "0x42a786c945032Dd0AFaa89fECB659789b56B3FfC": "0.001902747861644057", + "0x43E6887aFcF79DbB6aD9c0B22f802B77fd7c6404": "0.001950850611772753", + "0x4442dD25DA06786c78d8874fB33381E706877FeB": "0.002045392642312193", + "0x44C642f69a39F1b2b788C013c3839277cBb24DF5": "0.001983616606745826", + "0x454fd6d5FFe4780577ce64e7B17B39BD80158021": "0.002200839051644971", + "0x461980B8560EAC362aE5E685cB5a35952714611B": "0.000992761419614184", + "0x463bECEc49d10Dc785110031B9F6AfFbb84b6aAE": "0.001304490755382015", + "0x467c3C9D910fF352c7472571d3360bcE53c2F6B9": "0.002817229027824432", + "0x468876cB9b5850359609Bb4Ec7977a3f41AfdF75": "0.001203599383669484", + "0x46Dd430cD21e39ef9A06b40406BEeF25B3810210": "0.003142803920990852", + "0x47A40A367b3298BE3da3BdE3994c5342e26f368b": "0.002574440801490452", + "0x484637541D68ec3627Ae6E2bD7192E167b88E93C": "0.002889776300040188", + "0x48767f20ec0aCA7f47b3dA2Cc32Bc06549470A9B": "0.000519569925810646", + "0x48A384D082C97f82ABDaC55e43EE8f2392b9f394": "0.004047524464547004", + "0x48c7e0db3DAd3FE4Eb0513b86fe5C38ebB4E0F91": "0.0001090248", + "0x48d26F8F052d80E943694360899C4bB83344FdBC": "0.001719069438432509", + "0x49135912edB24205E1b0E7b9eA71887edC59D50a": "0.000421542883416198", + "0x496A936f46dFaa912F128CABFA01BA6F56a520c6": "0.001115920301574156", + "0x496cdac4854423c66EB0Da89f9e96Ef9D8312ef8": "0.000876634598008012", + "0x49b3fB1B5E6C6Ae2A0F15dE68F73F9e5Cf99Bd78": "0.000165806687619094", + "0x49BA7fC7a31b6d49e0C7eDcFF76C1678078EC8F2": "0.00030506313509658", + "0x4a194280157860E8aBfB7446Cf9eE84bf66dC839": "0.001650531881154534", + "0x4A2e4FD85Dfe564C5b14A134AcdFcD531a5BdB92": "0.0003379454536506", + "0x4A6115D5ee87a3Db90b47881B7d6e29802DEe62c": "0.003829541985395866", + "0x4AF5B23Cf8B2EE85Ca974DA6a51fE12bF726Ae6b": "0.000477202257309814", + "0x4AF80E6414EfeD0B91FA19c0D19B46C381beCB7c": "0.001131272892735052", + "0x4B8aef878255F6242606Fe5e73D659004F5A34fA": "0.001585130521359351", + "0x4C7D5a6437B325A998f83d9dcC267c5fdfF8ef56": "0.000772818599011801", + "0x4C9B462e44B14df09912D99Ca7a0daf9fF0d6f77": "0.001411727440103071", + "0x4CD6ac17782D95DC7a8eE2106fF8de4a52984B01": "0.000235348811664286", + "0x4cFE0198958D72546c4F8E415616B4594DF18679": "0.002801481749290462", + "0x4D2141b31437E970A0f13c935180194a8C4308C1": "0.00205394078474958", + "0x4d237f8E3364Ac5104765d287cDDFbD52b3C621f": "0.000257312493278815", + "0x4Dfe8442Ad63763E7D143BBB40F6A9A76F86a551": "0.001378504412637978", + "0x4Ed43703F882CcAC37897Cd46c80e0462be5C91B": "0.001671144164619649", + "0x4f49D938c3Ad2437c52eb314F9bD7Bdb7FA58Da9": "0.002205644371239276", + "0x5002a9263908CAb85BB4c71559227647F82530e8": "0.002916957364213548", + "0x50229CB8317ECF297E65cdDBCe88e0814eecdf9E": "0.002130687755108406", + "0x5060020e66031c324f77ae24F14Cfcea6A688Cb7": "0.000436805264451654", + "0x5071e6d385f584B5875166563c1670460905ad7B": "0.003897061222411612", + "0x50d26FCb38a279043bA075B86df912Cd523931Ef": "0.00099617178833104", + "0x517E758fb4095a1D250D084eAF16DDd041577A05": "0.000418521973844092", + "0x52A11a19528DE46078fe1118aD45540A5ee514bd": "0.001302019002861303", + "0x52b88b1f9e4B0E8B3738c2f4AD0EcA5B73ab31F9": "0.0024326559705695", + "0x533758cC4EDF0568E51e322367A9Ec6fbE24E9E7": "0.001557848461192187", + "0x5381B78AB971afD2ecd44F1431D635541aca696f": "0.003438903181023736", + "0x53A30736a43c413Edf5C13F049D34d3Dd57B7128": "0.006332039302005524", + "0x54B74D49cbfb92343E4607F260BE721b208b4dfB": "0.000362656876207634", + "0x54d6390e19Ce818209bD3B53a5d0D2E0c6FaAe04": "0.001099071979430954", + "0x553E206F3F504c3E02258cdB93614e0115827D1d": "0.000995348388598626", + "0x5576023B904E1EBE5c35c7C041bbb2806e890163": "0.001551113132212002", + "0x55AabbfA2e5D574F24aF480E181355DC788E0Cc6": "0.001550301160922042", + "0x56719d9844bb7968941fe7942462Fc38D7448896": "0.000351628609946178", + "0x574c891acEdddeB18d112DcE69F87241794307c7": "0.001001537126390391", + "0x574Ce8Eb2f3BDC44Beb64eAA9e629004276586d7": "0.001841006912831389", + "0x579fFc05d22484336b803DE2201Ace27A5Ef5e0d": "0.000683903625555655", + "0x57b92dfC53d2D50135946b74C02f0E8c472A2f11": "0.003034112585321238", + "0x57c106cD365B436aC4a2Feb8690CC29FB32E8773": "0.000558955922466647", + "0x57fDd988547aEFA02dDaAE980AAfF0B031924D3E": "0.001241214821572192", + "0x5836Df3DaA6E9B97434F77272a3e8ae3c478D0E7": "0.004138713207712326", + "0x58504a178E3A3B8B65E51a9014679550f1dC5a86": "0.001830886196590977", + "0x58706B388caA1D46091F1FE4559F6BC77402B44C": "0.002665148578325707", + "0x587Cf3Ea6bdDB04A5C6912AC95120443f4474115": "0.002277413218547596", + "0x58CFC8ee2132847AfcDc67CdeFA92b2D21eB5Ba9": "0.000984847744131868", + "0x590a8DaE6861CDc2b0300096ec6E4dc6cF2143F6": "0.000405833426453988", + "0x59760d82C6c5B6B6F8865093820B74B5325d775f": "0.002091237757157023", + "0x5A7c9e40Dd0b4173d368c3A810E5fef2E92F73a4": "0.000555494147591108", + "0x5b01ce79D8b3B793DA3Be5e27de3A767f1a02eD2": "0.004090213034835558", + "0x5Bb7e188594870CE0296CC083aC74C35B2565709": "0.001189219689035914", + "0x5BC3D8339754B5D4455355B3C5CF2639fB943942": "0.001058707797710202", + "0x5c4907bF26883c8dB9cd38F314bB4DFf710593aC": "0.002828673988841977", + "0x5d2150E5d88A30d5793c6C49959B8f7d350a36A5": "0.00062317021023243", + "0x5DB732749c6871540f481c15eBF353fC03c225D3": "0.001579445299430718", + "0x5dC0A2903554A228D9331ee0748F1A712d1E6d39": "0.006863964665223741", + "0x5e4180eADCD9328c0dbFBDAFcFfa73c8eF831Ffa": "0.001782939204355069", + "0x5eb31519474Aa90E492168a403Fc2AB4522ADc7b": "0.00143006919015883", + "0x5EBC1D2809f4DfcA9Cb518EFd2307fDFFC36D55d": "0.004396707672251835", + "0x60307A482765634C9fdb773fCF4066bf8614df8B": "0.001786812667424917", + "0x60CACe9B90E3A1E6e49b1EB16BdA5fA631cf23A4": "0.001752650545741213", + "0x60e0D8fef5d86615067dD713cA3ecCB2dC669993": "0.003183531176946441", + "0x610C6f79839DDA54E8a587e279E6e93a0BF589c8": "0.002039304527156259", + "0x6137A7c745CE7ed7a6eC8cA4AA5B635fF17d5467": "0.001118648746654506", + "0x6147d56b02faBD35cd9fC2B80a60276cDf089521": "0.007326360624243218", + "0x614C52345D9a2542460a765B7332016BA73599e2": "0.001361811851143692", + "0x6209e6ABfEE4Acb6Cb6C2d5FF8CAA35CD9B87984": "0.002448488320059453", + "0x62A1Ac16f4Bc32Ea0B65795031E75419a46F8F01": "0.0040086091843321", + "0x62a3e17519aBCE8b5B12A92f3E01bB6b5CB09751": "0.00192670093424056", + "0x630A63523A4f079201fb548114695d8da1d742F5": "0.00044897364183439", + "0x636223B012C4d186153CDDd584F3f4F733257Df9": "0.000939801620133649", + "0x64125D5e793b05F0290e4d322a5b05Fdd3EC2674": "0.001317701293673964", + "0x64230Ae13E943e41450061d01f38b606E6dc996F": "0.002025486495699609", + "0x64dbcD6e381a4833049cAFB83eb6f441349B2F48": "0.001279016189798426", + "0x64F86C703002b9fB260C2fC65C15ca0e65530fd1": "0.00176381571977205", + "0x6573e30Ee0ad46BC9aFA0C2aDb0D3f147D658EFE": "0.003157830075647647", + "0x65DFdAec30d18F98791153A92F1f4cbf64839Da5": "0.001171524258265209", + "0x668D123f7AaB549301D9444E582Ee4ccd379C4f9": "0.000256239437651421", + "0x66A93EA89C257a03a125188f8eB742972537bA85": "0.00289610883123106", + "0x670aC9fE190AB0Ac2D6829eE414F221794B22cDB": "0.000367961554486094", + "0x6748445D83259a6709e459873323324a54072d1B": "0.0004125245335512", + "0x677350145860d4937CC04bbD29333C321862Cd19": "0.001810100757137645", + "0x67b4329df2274F21429538a1Cd35bF604C35dB59": "0.000617427740993167", + "0x686c4D2ce918805D05FD93F109e279b0c3DC8Bfd": "0.002697900891135362", + "0x68Ba3e38585941E2aBEc12e18c6AC11E15052292": "0.00120725538056029", + "0x6990d1288EF65F0d0AD9E2c54d1ABc91118C64ee": "0.001512452283223035", + "0x69D0341d380a1229f4751a0A721345dBc716586C": "0.005333525067475858", + "0x6aEdb6460ABAE82F5ED77aF1d5e9Fe6F701d8c4A": "0.000887279887748914", + "0x6B56fAecE16358B3e63b231837963465cB98A152": "0.001459143800064487", + "0x6B7d0041B1B05f1D8f86AE923Ec09557e32Aa416": "0.003073934112787674", + "0x6B8F4dC1D7D243a9f9b506D58020c866EB199885": "0.003176410682534911", + "0x6Bdb3A8ae008cE1d3073870c852010E089FE6753": "0.001872626148991244", + "0x6C9b8Ba06E2212D29561A5910f418a042fC788ac": "0.000273335624404536", + "0x6DeB5c18F9d75d5D8128F8F42cEB225dD234F960": "0.001627868877751568", + "0x6E99c76778B44b430d5dAc1559e7AA9DD76dDac3": "0.002352943406227767", + "0x6fDc3F38B32fF607199B7ba12459D741CA6f4357": "0.00251976638956371", + "0x6FeC2026e8E468825ED243445508f1bD1215059c": "0.001926101782739981", + "0x709e49864C46A307e8f383c6B0094062b74c6765": "0.000832106669875826", + "0x70a7EACE9F44F3C27832f92Cf5EFF9B7ee3Ed2D4": "0.00033741151530551", + "0x72CAb6D1Ee9676DA8956A7A8E74EcA4052d19696": "0.003437454405732068", + "0x72e1260FFa7e3e7F41eff646B24694F8c139c73d": "0.002110320098252279", + "0x73714FE3e21C09FaE810380c15C64b5628E5d904": "0.000498372346319018", + "0x73A5db333D383155D2E4fC506c2802B557108E51": "0.000230977753115089", + "0x73cDE0e4F0480EA6B98Bfa292Ea936685716af4D": "0.004182221756493842", + "0x73fcB73D180D013ae1dbE306DFcD59C5Ff01b66a": "0.000333931769184205", + "0x744c2f5FadbC305d20Fc91274b71a6896d294946": "0.002154405987584555", + "0x7460B763e92f58f58B80F6650B41F3d2cD10fC3a": "0.002068248961183268", + "0x74C9DCb37E9eFb795d4696212E8ae4c68C4d3D1D": "0.001223240999749143", + "0x75F223915302B9bA12eD8F5425f88b74379bE6aD": "0.001110282436521396", + "0x75F5607Fe0A27c57CCd7B1eD244Eee9499D68302": "0.000853395997600356", + "0x7643d5cA36aec928C15181F02A4263D9E1FF594B": "0.002011786909719163", + "0x7645e40EF215f9Bc44F384a0418c87024646e489": "0.002044342586676759", + "0x765C6299ead6a2fa713E0D323Ac6BDc96bEF214E": "0.0033278527113547", + "0x76bd993BD4A08FE154690095Ec0a3DBb51a0eb08": "0.004076238444491684", + "0x76cC155EEE2e97A34AC53e8b89fc44690Da753a0": "0.00240577975892889", + "0x76cc3f2Fb3f451BbEeD11bF9F64Bb35f43438829": "0.001990813064873342", + "0x76e0eEF2E4883f5163ACabBf1C00a8eb73D25d83": "0.004764401388187936", + "0x773B42430376334c327831C1AaB73f44A379F58f": "0.00038044383161311", + "0x78044a54e9009eEE6aba5A9418EA6380f153a7c5": "0.001874776999470425", + "0x78be141970C8378Ff7E14dc0E817Cb17b342F5e4": "0.000409374561948349", + "0x78d964e9629fD6104F8F13d0DEC2485Bc1a43A2d": "0.00120915164941758", + "0x792ed5735E87859792f96bE92E98360fd7c76084": "0.00056833064235356", + "0x7975ae9ACd918f2c2F77a365e9077d098A102C86": "0.001818905533266983", + "0x79c8039C0cfBDC3cdF8d66eFB1AD2836E698ea3c": "0.002745207218955531", + "0x79F7f0B17404756c405be60A60A491058C627958": "0.007808654191542071", + "0x7A75B62e21C490fe9a27A50a083D6a2b04c7fbbf": "0.00054190741796834", + "0x7ab3c28958844A758FFA564F09c73dDa7Ffc766d": "0.003062750855771312", + "0x7b56128FAB23816D4a7520Ef691e2607af97B01c": "0.00087502027835499", + "0x7BAa3b328603535006d76D7B80aF7260FD8A946a": "0.000450916094931589", + "0x7c05dE20A59b43c0Fe27eA1B85A2872E9EA519dE": "0.000297367085888908", + "0x7c9c7bB3D6880F0d720fEb4fA6164Bd3E49F76ED": "0.003325422172311954", + "0x7cA4b00a3aEc07F978D127E69bC16484a038619C": "0.00045013115069857", + "0x7ceb2a5C3395A5cfE09B66E7cEd496061301c316": "0.002232276676490786", + "0x7d822dd2320B0B079db5DFB0b87D63A0E9F090d4": "0.002860405156906349", + "0x7d8AEE804Bbad88d0081115Adc917F5d9bF6388C": "0.001899743234221034", + "0x7E1B249e6BAA2F60A87B14b43B1Ad731542bD9fF": "0.000700318590733549", + "0x7FafB471bad0589FaBa53769DD8d76c5d79aB720": "0.002629024243659779", + "0x80040d9c574156125E096d85AF6B6c86668d6CDF": "0.002222021358202793", + "0x803E38C54240244046545B421FfFE4e05BCD5D0B": "0.000403060462062888", + "0x81502de049CE028C2A91e9c91d059Ab8Da8Bf469": "0.005036699466795216", + "0x816a7FdeAA4B1Fd5CaCdD337d0A815347a5E714a": "0.001813361626403986", + "0x81864365b031c138Cb6a7c64526C7357fE4FFA2D": "0.001529874518478847", + "0x81B73F850A76D405bdd976Db6744D85c65fe9330": "0.003353245962229773", + "0x82074547555355BbE037e0E504d0D0C08EC4dBEA": "0.000563930998939954", + "0x83CDb49eBa3bC99AE57F5abE9c6cE9D601Ea744A": "0.0012501767793338", + "0x83f7321a05876f0bF973bEc3033858bb0b91e37f": "0.000253576097907972", + "0x841499f8F5F869c20886D581641DC181E9C6B672": "0.001789989869958947", + "0x84252729ed32fA0fa1b454b8f58B71758239d627": "0.002068626974566218", + "0x850BF360D7062257203854cEFc9A1629106d7a61": "0.000233865148295339", + "0x853E5f1A139FdEa47273A4632c70368d095070Cf": "0.001471304823364316", + "0x8578ffA6a6E9908B454CD38B93D3F11Ca8723A9A": "0.001898155682365782", + "0x8594E5a6f67cB13CF525EA15f2e1FaC3EeF63304": "0.002427596232541171", + "0x86CC5e1e8fb20102Fa7A0fa4afeAf1Cbe1BE273D": "0.000679366196250462", + "0x88330D5c152A3A064b8883ddE2A8a2aa3e4680fb": "0.004364686106772601", + "0x883Bb7134b7f5673b08fb8d3c31814B55bec3a43": "0.001391344852681121", + "0x8891E7796d54cF5b801F0A01966be79d7cC2a89A": "0.00231702783426477", + "0x8903349C5B3205Ceb9D004A051DB554f70D1Fc62": "0.002017975534804761", + "0x8a74781B294238d74f86B0cDfD4eE7b1dBE55d7D": "0.003417530192247443", + "0x8b1728Bb25502476d16CdCF0861669f68c91A9d4": "0.001247214210686356", + "0x8b992B29e691058a1EDD32378dc11E6480E0eE24": "0.001827176639363206", + "0x8bd7B5E860998607715Da42944cc9DE3486A3Ae2": "0.000699346289814744", + "0x8BE6B927c4F3aa56D9c0DCf1be363b0081Fe0BD4": "0.000376122121756596", + "0x8Cd66785F2A1B5ADc3Cc81177D485A8395Fce2f2": "0.000656200320462028", + "0x8Cf35646c42DA86292aBDCf64bd0f7e7fC644a1c": "0.001451440145564425", + "0x8Cf75F1D6974DB5215d81FBec287Ea8EEF35C95b": "0.000519927519621719", + "0x8d3450C45C789Cbb6E03baF1f939B8081ea41Ccd": "0.0018214506906328", + "0x8d47CD9B8b015B0F3865e8eE0b96b8125bb1F483": "0.002040355617210643", + "0x8dB0696b0835031ee2166F130d90Fd31EfacA4E3": "0.002653146287240826", + "0x8DE1cdCF6D3aCC777d08e2359Cd4D6Bc72e382a7": "0.000438739746115682", + "0x8E561b9823d9BF7067F5F64980aE26b6b9969e77": "0.003646453781237505", + "0x8F559d9F555131932345C2A9546df023c54E096F": "0.00098866912405153", + "0x90483C0d08A16058aB7Ec4455B8Be51a30Cc5043": "0.000588149937616228", + "0x90942873BEC9aA28a4957c1FF1C41fb3B8cf6a74": "0.00036617205785523", + "0x90b979c9E90EC5D5246dAE6BE32ACC451edD2464": "0.002100757033999859", + "0x90bd7028416753B38714F32acdE927aCBFD7D18B": "0.001889818145671654", + "0x910144b369ed067F8a2ea470ebCC2Fdb31c0dd9F": "0.002797157336750915", + "0x9247154eB39429505f75096d5A6be52acE076A81": "0.00135806585325456", + "0x929cB3CDB2C23fA479D72c21731C53822f5df881": "0.001448912903002483", + "0x92A5D7978E46759EDbAeF30012E4c60C8DEeE0A7": "0.0010956087692927", + "0x9301580990202CA724E2d2d3F2Cde88fF50735c1": "0.001684434109070633", + "0x935eFc16A75a6f0B59fa91CcD21Af633A117f97F": "0.00370337099812257", + "0x94478F8B27CeDD6177E238F48164A45245C854C1": "0.001102472607435183", + "0x94667C16eF36c34d6De71FfCE6E80C5d24672a41": "0.003389708729565961", + "0x948F052C6Ecb37aBf9f81b87c620Bb272E422155": "0.001326655632232697", + "0x94d0f3A10f88A63fcE0F2304ed63D3d166fdB313": "0.0020490265361758", + "0x95aFE39b111176629BA6eE5F2C1c86eF973226FC": "0.001674189479987855", + "0x967bE9835Ca02EDf7A8c7dfE26519763c1611277": "0.001796203191079962", + "0x96c00fDDa3f3129A55C0Bc9b48Ef504C3D5594e4": "0.00299180331265087", + "0x981387F73e94a173F9eE05a7906E299F99E23114": "0.004312837409283606", + "0x9860D7309039b9A44B1df878Ed4484133a881316": "0.002384094674163708", + "0x98EA9cC7128004b6b09D0fF7F922cCF51D6869CE": "0.000265932280527395", + "0x999EA3182C60ae6F58817C77Da6A769f6f731f34": "0.002049352587514968", + "0x99BcEa6bB0403927fB3c038163478D5b42082Fd9": "0.000874116431832116", + "0x9a0705ab1Cb8C5139171911cF0a689DA2F54830d": "0.000595677795656707", + "0x9a4773EeEE73e34e1EE0E9A64E4b7453b0b04246": "0.004769169014342945", + "0x9A4B6F0839637769e14DdFC03D4E7c537d8e25Bf": "0.002862973385887932", + "0x9b5d6a05E969f58438780d775C0037884526877f": "0.003168447002507213", + "0x9BC114CbDf47021f15416e720bC71b5341120E87": "0.000522280134489487", + "0x9Be6FcbF8d76201559627BaA8B0cD60cE7e06b0b": "0.001762480396329596", + "0x9c0bCC942E775cdff33c64906561A3d75d9D0B79": "0.000125010267582388", + "0x9C9A11a94f95cd31c06E0252eD0cE908b90FBc0C": "0.000317605393089572", + "0x9cDf01F751864333515c209B733501FA5bB14143": "0.001121291953792428", + "0x9CF0Ea03C7e23f2C466d48f6BfA14A85EF7CF4c8": "0.00054107608076499", + "0x9D3a7C178E38748a3a53BE600C922aD5fC45C0bf": "0.003126544705690538", + "0x9EFA7B040eDEC79662F0a7bacddE8bd1db50a8C5": "0.003506710586183753", + "0x9F9a6867d9Ed4630DAC6d3F9C125248600DF03BE": "0.001617015067675783", + "0x9fDB970aEF60007FeE4EA132B5f4EBc376740aEa": "0.003869483672880516", + "0xa02B48ce476ADe8A3f635857dCaF9475F79AD6EB": "0.001616189840039979", + "0xa1df756B063A867bfB3cf1fa611592Aa646bF4A8": "0.000705177083941647", + "0xa21cC0DE85E8c75bB10519872Dd3965ceC351e3A": "0.001173703038582787", + "0xa2E5Dbd496e25A194a11FC3e4Ad5AdA199e827F4": "0.000190120981281462", + "0xa31c2232842e631cCb2d2E4110B356Bab21E6020": "0.001806977094637775", + "0xA33c3B5Bd387B26F72E1c5e76bc1bb81e7935EE7": "0.002904722801428504", + "0xa33f0D43b87dDD418C029412b6dFcFA8a9C68074": "0.00034981925850061", + "0xA3625b1dCB1e99dCC1B9BEB6ceD0965FAF4e20e5": "0.00027416594484952", + "0xa3638f8044d928b42dD74085284bED980b0e0278": "0.001489714764094299", + "0xa3651cadfc97186D5B93A0aD7Ea32C126a794BFF": "0.002467720955045497", + "0xa394d3bD4416380cC3498af7d764fe1Cf76A69C2": "0.001963537059139433", + "0xa3C18bAe51Dfd07FA152492d685c457D0fEE09D7": "0.002029954724613294", + "0xA40ee0717533dE5b87D6f2054AEE815B8461126a": "0.001482451760135974", + "0xA432B3e56A6F4dA4574cDF2f27bea9bbb5543011": "0.000741758386152588", + "0xA4635d0D583F6A5335Aa3CE39CA7D7c2e7a7D01C": "0.001081951101240274", + "0xa4bA32A41A317b970c4ADFE1e1573930c2B4551F": "0.001101759684429442", + "0xa4c8e8D8983e53381b25967659A368f8E108aca2": "0.001392081305519205", + "0xa5D2817A0d9547af625942E6F3a3bEF71E5f5Dae": "0.002463406117634708", + "0xA65EE589b0353e7cd63c03FD534bEa61C748c3c6": "0.003122326719810565", + "0xA6A162FA210411Ef494feAAD1605c415f8fe0da6": "0.002876036318224835", + "0xa7A56D141C552cfB45b4AF6aBFF0aB76f9369c28": "0.00287960685857875", + "0xA7e781E2EA7740177d9b9E13Dd2134A103f5833b": "0.001707803355211447", + "0xa85160a81da205AE57F6d55F16C9C43d773c7438": "0.000328418143729698", + "0xA89fFd4063866481f3DA231bc2cCf88Def15b642": "0.002201741825983557", + "0xa8AD81A7f78a55E02f6267F2568e96445fa2A469": "0.002754570288532948", + "0xa8B8f0B17Ed13a3663A8E3f169C42464aDddB984": "0.002547112551875254", + "0xA8E20D1B16c2821c2E17A58eB9c92c2ec7699283": "0.001759062914952147", + "0xA941ADc6DC04b0cfd17Ffa75329B680C9A1B3eEF": "0.001822412558997712", + "0xaA8eacF97AF9Bf3eB4cBB76E975a5D6aaA220606": "0.000364739785325574", + "0xAAfA1bF92688084C3446fDC741c1453379cD72df": "0.001078139579160549", + "0xaB0Ea94509caa5703362EAaFd8087d205f97a340": "0.001233541625572076", + "0xabe5B6e8a4e79e7F27DB3a6d9E6A6f05e521f604": "0.002119653671187518", + "0xac2c2C3fd735c5DB2aB77D8358DaeE705932ff3C": "0.001378735155214537", + "0xaC880a2568c6F5719AD59C8Ea3BC11a910775757": "0.003592688241339687", + "0xaCB4FA704c4A7092B3373D5c57443ed3261fDD18": "0.003630255800827459", + "0xaD82CC9A78F2cf917E56e6305A01424b9107EC43": "0.000907934643521791", + "0xaDE8502eC7a7Cfe5fc273cE3B94736BB1F76118A": "0.003916966524232559", + "0xadEF6E3234cA45D5bc3C2bdDD4bF427862c60335": "0.00102697588125076", + "0xaEd91598B3ad7e4b6Edc0fC2a0D9E16e8D58981b": "0.002529784784036854", + "0xAEf6a3580A365c524A5bC9aabeB2a13c2A1a7B7c": "0.00436429371858028", + "0xaF4C815CF13Bc8671a2a12BdE62aABEC24651ccC": "0.007448462468293356", + "0xaFD255f71cEBa0c0EceE10fa52F3e2fbeCcE95C4": "0.002017913554351507", + "0xb020747D162105158f31bB6Fc0B6DfAa66B23EE9": "0.003081457554423888", + "0xb187ba422872C0467390155826e5290Fcc9fa3Df": "0.000669892488329972", + "0xB21bE96Dc75717272402eF97A5CC144544263E3c": "0.007989764775625071", + "0xb2a275B464EdcF73c70EfdA20a5Ba5f742470D4e": "0.00080688572111893", + "0xb36268588ED030B4d8FbB22a0B4ECbad1194e683": "0.003581681129386093", + "0xb397dEe549E3FDF24C82b72707cb6FcD849d214f": "0.001127914464566378", + "0xB3983fd5997711935dC61118e684DDCA1CE3F8C7": "0.000298691331723346", + "0xb4C907afdA8C362B58281B5c43A2e7b79f089D09": "0.00043259757817898", + "0xB538544c0d0971dc6cdcc17a1Ac50A02bc0A8B0F": "0.001446947123780433", + "0xb67a6E67072025C1db86e552dc17f7Bf9C296122": "0.003520536193415728", + "0xB6e74e6fD559f9207679D128ddDBb35B9042A166": "0.001782015073476024", + "0xB73812cCE6F5cB7ada40A134b4b16AefbDbB9472": "0.000335504749350614", + "0xB87000FF076e59EBBfD973008Dd21941Ff9D13b1": "0.004408962239023198", + "0xb87087bE41D0299e31ee8c274540a8bf15bdc1DC": "0.002544955155700901", + "0xB8B5caDA2A1Ab13f421870555F99887e3d6A2e77": "0.001861507909183529", + "0xB8C8D5Ca07C82e7E4c73f0cE93E2a7dD08956cb2": "0.000566355500311814", + "0xb916A83cC28F6f63ca9807AD3bFa84d9e14DF963": "0.002088068889187287", + "0xb93EFD0e79b769D2b3Df7aa64d89F983D2fd02FC": "0.000337327081910856", + "0xB9F187188A9cBF21b204F125Dc116a997fC29aE9": "0.000270307464448756", + "0xBA93f72e240d7F45DB22EbF126c2D87dDE238918": "0.000760381014311528", + "0xBB323229972D001bbF725b3fB3734eE53B7455CC": "0.00041913220343746", + "0xbB6aDdBC9C95100792Fd80FEE1cfB46881DE84b7": "0.001306095906016642", + "0xbc45a7315eda040A0e0a53E022b62042a71077D4": "0.000287544605221634", + "0xBC46980A01D8301D336fbf9377aAe711d34fF122": "0.001833265197573606", + "0xBE71d84a622010A0C9709a443017FA53419706f5": "0.002003770387416666", + "0xBe815fD2CBF30D07b804d643FbEEd27b8E663acB": "0.001385352508463922", + "0xbe8bD46D8847a8319261F6Fa137156671dF68982": "0.000230976636674221", + "0xbf72eE28dc8627AD3e76bdA841247EB39837806F": "0.001899623293470812", + "0xBFBcD879dd913255B32100a72A581C963e7b0ADC": "0.000299029647509498", + "0xC0867A1D3deAd93c0E79Ea3fD54422671BaAbF37": "0.000256529672672097", + "0xC0AAbA6E0dD2Ca4C2BE7Df446C121C3E6118bdD2": "0.000930044726786784", + "0xC0Afc9BaEcE062D4cDbbb56eFBe33BBd827e560d": "0.00129605226073346", + "0xc0c13E73641080b8a890261b731f9872cD0bC9d4": "0.000117110196735569", + "0xc0Dc4010e76fbD53C82b19f8f8d7604e37289fB4": "0.0005085470286171", + "0xc0FdAbeF949f28332f596e66eE8e06a13A103c02": "0.002197195124105275", + "0xC3Ac3355B2686Fa503246a92e34D0B7261b39d6B": "0.004108176013136093", + "0xC41A3d9ED9DD925fB057b7C1599249CDB4C6B66b": "0.001776535432640127", + "0xc42851d834037cA1f82668596233DcA69654867C": "0.000558941540925206", + "0xc477F54B5ABBc255f366aC54FD924a896da5e6a3": "0.001327406402168072", + "0xC4E70E97A54bbf4f9796099282fA47397da4b4D9": "0.000665931259830168", + "0xc56d5742F3DcfB9Ee9aCBf8d86385B61b1F0bB33": "0.000733689799816614", + "0xC573dDc59824F248D3688DF0474805F35C2C09c1": "0.003429880143140206", + "0xC590314dE55b52C96eb34eDbC4b55cf8Fc8cD510": "0.000468622920904", + "0xC5b1624c0aFad0E366A9cDF80C08C3ff8253710e": "0.000716488718332234", + "0xC5c90045A5D097625634C7d4bb7dBfBb8E3310AB": "0.002151916154445083", + "0xC5E789964681a9ACf7D8C84EE89252Ad531E6C8C": "0.00209505471583887", + "0xC636DA66cfa5c363C4785835069dcAF85ab91feB": "0.001650890862846228", + "0xc73f65Ea9d3d3c165cC6Bf31dE607cb946B1e4C6": "0.002086677225362585", + "0xC84FAc7D2F80D70b21A536Fdc1Fde5cb404d747B": "0.00706528481413282", + "0xC8a4C0aA604f225aA006835672CCb68e661f7Dbe": "0.001023872103175712", + "0xC8d23C39c8F808D599b65D4C9eED01B8580a66bE": "0.001660993596091826", + "0xC92b2aF1B472D39275181f502b9d369ad9507DbF": "0.00021049570852914", + "0xc92f8051ae3786fe90CA5aB89361DAD6730c4Eee": "0.001914942211312756", + "0xc9B1B3Ad7546703a9AcfE2940287ae7F9CCAAB70": "0.002884264749883987", + "0xca30cE2505F78e7B4f07b2d0A0F22eD62B19051B": "0.003023154432565645", + "0xca49ed45A7d23193b0Bd2BE322D4F0C63168b34c": "0.003175292204874449", + "0xCB4bB9D616f27dc84a256b768B4C393fA8010caa": "0.000384449569462733", + "0xcB4E72E300390B3E352f20787300CB741fCDE09E": "0.001485087259569859", + "0xCb8c77837f470053F91E1e288CAc223118C69937": "0.000520092891168132", + "0xCc50808A98AB15312361ab4837f412B2d9cDdA38": "0.002129457522390259", + "0xcD6DbaC9cFd5b348744640D8ceF05f1B5245e2E0": "0.002589611500333746", + "0xCD779f2e141fbA5A332A8Ae7882Cb1aD86cB8D34": "0.002958572598237754", + "0xCda9C44C18c5C83963aeb1681fc4198542650345": "0.000899944832054884", + "0xcF2e28E5E57461254B8B254AE6D03c89d19BF743": "0.000612845037124201", + "0xCfc1D59675355d5288C982d23caF28a2D0A6d48e": "0.0021166793112989", + "0xD02524BEeFd5164Eb28C77CD3eb2C7De887B891C": "0.00072549399647567", + "0xd04383c1e5Cc572BDBebBB88a1292F9aCe70007E": "0.000875459348520922", + "0xD05F0F552d72947b471a4C4BEE98F9207E889482": "0.000357507395322018", + "0xd0A530121747B005af6Bed69426092cB525713d5": "0.002258230098316503", + "0xd17EB770E4E209C186cEDA0d7E09bFC03D792b36": "0.007854743410674208", + "0xd1Cd2FD35C63e27A33f0b5ECf9C92ba1AB9c6dF1": "0.00046190163348943", + "0xD225626025F48Cd43cb35CE935a4F4B856AEd21b": "0.000617205280198213", + "0xD25f7e77386F9f797b64E878A3D060956de99163": "0.006008179777689715", + "0xD27122760634f46994815A2B5097FFF7b0e910D5": "0.001450915497136981", + "0xd273f87e43851Fa7f0518E3B385c0d964621E3c6": "0.000544471694479184", + "0xd2Ad096Ed0757dc4954f66765dea737e5a687dfF": "0.001742186993010333", + "0xd48010De315e10D071853b1466f0C273e766FA07": "0.002784464923297565", + "0xd5769DCBa4D94716e860431Be65c0c84C379fFD3": "0.001324700945656694", + "0xD593f878270b61e64fa65dAA06728D0bA89C792A": "0.000820867618037016", + "0xd5E10116D747EFC7028fac192093D2AA2Ba9EF12": "0.001676456834983982", + "0xd65e71C781BDd00221eB77B920298663D0b83484": "0.002211278863920194", + "0xD6CCf8Be80aa6ae4320AB4D6551C6f3ef96AF7aD": "0.000486618749418646", + "0xd706bf4bb1560a73790D91B8fd585Cb5508db6ea": "0.002308707028848392", + "0xD7D00580798FA514bbe9b71F3B84209f83Ad5bE9": "0.001984546563744876", + "0xD8C3cd1A7576efC723357B7158318f0CeE0e30F6": "0.00044068200908034", + "0xD8c50C68066eFE49bC12658A5D7C984E7254D417": "0.003099888050457143", + "0xd957f2298bEFD78E946643602fe04509f45Bd5bA": "0.000230977753115089", + "0xd9e352554D0e4269d9B158d1baFC7975fd4d402C": "0.000760604591941388", + "0xDA6De31eB28a648884247708385a0B8027E6C4b3": "0.000790580459432837", + "0xdAe56179CbaDA38DB0A15da62D43Dc66306f746B": "0.002320295461415382", + "0xdB040b1bAD2941e02F6fea3a7f4a13D189E0beC4": "0.002004344134765031", + "0xDb6D77A78b4da7286E3C1A6828EB83D9F0cCA527": "0.001093054549561128", + "0xDbD9416f32c409b3c7A29655AA515bd717616470": "0.00325733870134353", + "0xDcb26b5dBB5F8798C1b434597ffa5e4aEca20d05": "0.000800468300315379", + "0xDcdc4E48c3DA83109322E3fC507181D65687Ef84": "0.001603467669571091", + "0xdCe31D9b0a5B0E2A40fcdf9A2ad73C3CE2071C15": "0.003834170421679551", + "0xDCFCAEa66D61Ac1B52bcFB647c03f56c0bbCAa28": "0.000511457002624332", + "0xdD2CB8c9b8FCCDc366AE60f4FE1c99813Ec0d18e": "0.008329671874649461", + "0xdd877AE95f4aD48b4Dc640F52E802BcBE3301130": "0.002270430581135096", + "0xdE7250D923299e1EcEDc0743b159E95B945082d9": "0.000434934982653018", + "0xDEf3560E74E9569d32339337D6A05f3F329D7a3a": "0.002032296297916199", + "0xdf9Bd257d55271851b8F75613542635Fc608CFc2": "0.002101255931292738", + "0xE08A026bAaC28a95041DB74Ba78CE93Fb6aC766b": "0.000538361162153996", + "0xe0b343b462aB6D0d3048644D1a85f287D46FC23d": "0.002914688519788281", + "0xe14B7Bcb3A2A9b2EeA0a53dCE0A60F1649660C4e": "0.000266237354997955", + "0xe1810961A12B5B38468fFc32aF3b5F8dA1EFdB53": "0.000446224064526624", + "0xE19243a27D28a8Aebf138DeaE361b8AB53862a9F": "0.003641340331583464", + "0xE1d4C898E9720979c898e0962a1d8e3A897f9263": "0.001372531944753518", + "0xe251B115E89036C0bc0a8Ff09B36f77ef6291D84": "0.001264864072616305", + "0xe2A2f2A338EB923454e331422e9b6ef872325Bb5": "0.000843577679845794", + "0xe2A85879BE19fF727cDB79Bbee733b616e7c338d": "0.001377601143189636", + "0xE30C4Bffc186667d5dA5EEfB505B419432c62168": "0.001840082632911276", + "0xe35c3f0ad5972eC28773b31598527a9A0D0B22a6": "0.007238533487009321", + "0xe36b79317a75b08384c33D21197c7e3273886873": "0.001227236915685986", + "0xe57fe5bbDc76E8Af1448550cA56e7E36c8Fc8272": "0.000241820836428222", + "0xE5E7EB7B5E89866A6D852F55BFE363EFd50D2F19": "0.003478915545574645", + "0xe619ea101759B9D0c5dDC36b59f1F5e55FEB76B9": "0.002359796399082513", + "0xe63757E3cD485C9b35b3a972fFFA2d91B8649483": "0.000986735864247628", + "0xe67d3b0BDfd1D853FBcE6C0898b464e332a67B18": "0.001198794239274962", + "0xe6b5A31d8bb53D2C769864aC137fe25F4989f1fd": "0.000753074201404674", + "0xe79464c19fe30E6Db25A74aECf65AABeb92A44dC": "0.00163463112987963", + "0xE7Ff7aD54492A38AfB99bb5d8B897C5f93A66f47": "0.000643100129523618", + "0xE82C23a1084a4fB27ED46628c40301c0f63F0C40": "0.001196899433264345", + "0xE86A48bC1D340Bc524d5529222F5b51995bb8132": "0.002739279128097161", + "0xe98ED74D2AEd7b818FA01A839715A917D1341bC5": "0.001032817481176946", + "0xea03Af40FA59Ac9C311187Da0f9b979DA073C226": "0.001978266469119038", + "0xEBac3e24c3f59d50a713F2c79535acd381487486": "0.001976383990070969", + "0xeC2Bae309d0A18D7dDfD4EA0f17a2f60817f4E9c": "0.000645933072947126", + "0xEC67006aC513BF20ac599B48f1f9F725C142BB23": "0.000722736064090086", + "0xeeD671a75689E7aFda9F658c8482B0939bEE2d34": "0.000233600555683327", + "0xEEEba9f78590f8C05c67b627BB67bAF22Ad9597E": "0.00027391236297332", + "0xeF7220723E580F03A8f8b076Ee8623b1dF0103fa": "0.001441243816484446", + "0xF055cbe9B6b30D64AC1D7305cde7BA6c0993C86a": "0.005628685590980622", + "0xf0b7e13a31eC9D21c05fcD91f71CB82498864D5F": "0.001361374639710291", + "0xF0D9A0C82dCdE0675E2E796f6e25E8aec3e52f12": "0.000877071736336323", + "0xF1De794eCF521Ed64bDd4DD55308361511f87990": "0.003713800514850269", + "0xf2009F3E705e48cD9E1d29397fc19Fd7E4870cBF": "0.001693162005814965", + "0xf20737e48160A87Dc9D1B26D8B63C796d2F1EA91": "0.007088051537280779", + "0xF3579d18e82E8A1353D58D1B5a7265F4f5844A9c": "0.002003183311098456", + "0xF39695c39EaCdf81D146cE6667E81476Ea9b3fa7": "0.002222254263173393", + "0xF3C162C189341D024ee753223101612ABF6fCf9c": "0.000982476308149558", + "0xF45E1A95ABCa5362844634106a1B0705CcCcfA23": "0.00181078691486248", + "0xf5bE8850b5758acCaD467dA86119Db517b8CDe0f": "0.001529318310414164", + "0xF5C14eE163B349ccC50eBe31500078f745500580": "0.001221438452773522", + "0xf5DF7a18dF35dA5EcFff6D55bcF920e3d8F6d5Ae": "0.003188873408831", + "0xf611B9A9F0d9a0DF279665b05fE338b29d53744a": "0.000904891143724273", + "0xF7FCAfb56130a2e39bD28e5115E90E6972b83e5a": "0.00174590331797519", + "0xf882F94D9fA5a7bb883D3Dfa04e5A43Fa057C333": "0.002919695715752449", + "0xf8C9a3f1E55b9a91E413A8C8bB9F5f84C6d246cB": "0.001487950376516927", + "0xF9D3A0a21eca45C45F9F476Bb4Cb40c1C4f3aF07": "0.002179385491415533", + "0xfA8cE8D44271201e9Ce37838ccb75BA482d597F6": "0.00110276420745576", + "0xFa93E76Bb7de1071D6f9C0f77Af883c2a944B2d1": "0.00078487359042108", + "0xfAEF14B594cae1666846daB2780E964df8557950": "0.001783208136309095", + "0xfb043BBaF380A06c01750ce0a6324e38eD11110c": "0.000604414447549389", + "0xFB364E4D8eF3bf2551550DF01e0c8d55D3A772EB": "0.000958832180440529", + "0xfb4d1d353f95e477235611ed67076E61643B5614": "0.002094968733111619", + "0xFC2ed2462f05608b6a21cf1A43bf24a6Ea08c4CD": "0.001852574099363942", + "0xFcECa6193031F7f1336Fa055edFe96555644Dce8": "0.002026048122277744", + "0xfCfA494c13409172109f161C428499B39682fFa4": "0.001918027966172223", + "0xFd0Be09AAADaAb67523e8c6a9A3c1D657aCB2B5A": "0.00457870320961811", + "0xfD8355b24aB8815cA2d76d1E495DC29B4330241f": "0.002577673853038057", + "0xFEAB4fFA81BCd17dFdC2d7e906662527697915d4": "0.000369892464405737", + "0xFec5287823f5a317AB879eF8F8901Ad21c7D915c": "0.003531197597318023", + "0xFfdBD837ADAe8558684111d4B5cf9Ca36F58569f": "0.002119049556324283" } -} \ No newline at end of file +} diff --git a/packages/affiliates/gas-rebate/rebates/Rebate_66.json b/packages/affiliates/gas-rebate/rebates/Rebate_66.json new file mode 100644 index 0000000000..88ba917bda --- /dev/null +++ b/packages/affiliates/gas-rebate/rebates/Rebate_66.json @@ -0,0 +1,644 @@ +{ + "votingContractAddress": "0x004395edb43EFca9885CEdad51EC9fAf93Bd34ac", + "rebate": 66, + "fromBlock": 24558868, + "toBlock": 24781026, + "countVoters": 634, + "totalRebateAmount": 2.0729797831799184, + "shareholderPayout": { + "0x11eFc2638184a0382BF1bb29C4047c6111F8f3C7": 0.000490053119378262, + "0x7cac2ab1CF9dc459ca88A85D72Ac94DE2691f1E5": 0.000497236239467928, + "0x2f8320C2Dc28681Aa5BBF92e79C37BE656a7D5F1": 0.002182016307453528, + "0x000000000000f8E4fE2a98574fa81C728e340764": 0.003165492700122204, + "0xA8E20D1B16c2821c2E17A58eB9c92c2ec7699283": 0.003198805618795943, + "0xB21bE96Dc75717272402eF97A5CC144544263E3c": 0.003870616888550727, + "0xe63757E3cD485C9b35b3a972fFFA2d91B8649483": 0.002615139847231163, + "0x6573e30Ee0ad46BC9aFA0C2aDb0D3f147D658EFE": 0.003109842698831793, + "0x240d2243D90E8968D0c8E807202bC8a2DE0dC53C": 0.00069769646350095, + "0xA882C04377ff264B776401aD7B5807F1eCB38A9C": 0.000462065569468198, + "0x28eC3b46262c614df6D5A3FF2726c9746F1d1675": 0.003888942144152897, + "0x95aFE39b111176629BA6eE5F2C1c86eF973226FC": 0.003932674650743138, + "0xdD2CB8c9b8FCCDc366AE60f4FE1c99813Ec0d18e": 0.003694961813420231, + "0x96c00fDDa3f3129A55C0Bc9b48Ef504C3D5594e4": 0.004188299127338868, + "0xeF7220723E580F03A8f8b076Ee8623b1dF0103fa": 0.004281732864577896, + "0xB538544c0d0971dc6cdcc17a1Ac50A02bc0A8B0F": 0.006548600391705656, + "0xF39695c39EaCdf81D146cE6667E81476Ea9b3fa7": 0.002900151771579633, + "0x260D417fBD1716B1375CD311f8a6677c4a780B3A": 0.002903133300618634, + "0xaF4C815CF13Bc8671a2a12BdE62aABEC24651ccC": 0.003573826739945111, + "0x6147d56b02faBD35cd9fC2B80a60276cDf089521": 0.003591528287257093, + "0xFa93E76Bb7de1071D6f9C0f77Af883c2a944B2d1": 0.00525890946268688, + "0x1CEe194Da1eEfe344fb2e7f46faB7D3A65C078e5": 0.005905400249850902, + "0x1DE746BB64222C304b38F84613745323cB6C7fC1": 0.002198638481805458, + "0xd17EB770E4E209C186cEDA0d7E09bFC03D792b36": 0.002155973031748261, + "0x3D65eD138686e2AD54006d4Db83aD4597D645370": 0.002119667239978944, + "0xca30cE2505F78e7B4f07b2d0A0F22eD62B19051B": 0.002870838792426511, + "0x24F16D0Cda8c2De21c762E0295C28d7249a972A4": 0.002737196557661204, + "0xfCfA494c13409172109f161C428499B39682fFa4": 0.003178929585311831, + "0x203F9674bE9782BC4B194625Ee9dC6800e65B2D8": 0.005169110811541627, + "0x4B8aef878255F6242606Fe5e73D659004F5A34fA": 0.002874120869956637, + "0xa31c2232842e631cCb2d2E4110B356Bab21E6020": 0.002647321184432363, + "0xD6CCf8Be80aa6ae4320AB4D6551C6f3ef96AF7aD": 0.001959193646517676, + "0xcF2e28E5E57461254B8B254AE6D03c89d19BF743": 0.002411275306115106, + "0x24eb1c355C05439819a23DD0842D5D038d1CA05A": 0.004036633452237557, + "0x773B42430376334c327831C1AaB73f44A379F58f": 0.002011895996323552, + "0x4f49D938c3Ad2437c52eb314F9bD7Bdb7FA58Da9": 0.003321518857933355, + "0xe35c3f0ad5972eC28773b31598527a9A0D0B22a6": 0.005088576069338539, + "0x79F7f0B17404756c405be60A60A491058C627958": 0.004934662122722253, + "0x2352E748C9C090f44a8418f74457554CCe8D0485": 0.005108917497094188, + "0x5dC0A2903554A228D9331ee0748F1A712d1E6d39": 0.005403049894995609, + "0xf20737e48160A87Dc9D1B26D8B63C796d2F1EA91": 0.004820635037725114, + "0x27064Cc4FE5bd5a20d0e5A21390a45F5a44Bf7D3": 0.006760783386936192, + "0x7ceb2a5C3395A5cfE09B66E7cEd496061301c316": 0.00382569834776265, + "0x53A30736a43c413Edf5C13F049D34d3Dd57B7128": 0.004920624622262555, + "0x74C9DCb37E9eFb795d4696212E8ae4c68C4d3D1D": 0.00357401208286121, + "0x2D29986ad59F77676c204d09b44Cd8Fc9EE7B6a2": 0.00316741235493124, + "0xBD73cF5baf12F120Ee3f6C4ad82df9a12649e578": 0.000409122393583034, + "0x2C492138498165C3f6fF94Ab7d0B7Ab6dD546AdA": 0.001077114190915115, + "0x52b88b1f9e4B0E8B3738c2f4AD0EcA5B73ab31F9": 0.001374823614960015, + "0x86CC5e1e8fb20102Fa7A0fa4afeAf1Cbe1BE273D": 0.004252225085989121, + "0x84252729ed32fA0fa1b454b8f58B71758239d627": 0.002720088806025529, + "0x40fE8993df6f3915540aCE94E3a3d86a48829664": 0.002556936258379683, + "0x5DB732749c6871540f481c15eBF353fC03c225D3": 0.005616928883405399, + "0xe06f0aCc775c6c01ec69C9Cc8969f7B6C4BF635d": 0.004818578861998733, + "0xc0c13E73641080b8a890261b731f9872cD0bC9d4": 0.002717969264793197, + "0x2c26767989D49215d249e6D36F8e3FE2717f7DBd": 0.024761705568457075, + "0x4CD6ac17782D95DC7a8eE2106fF8de4a52984B01": 0.005254288031872111, + "0x850BF360D7062257203854cEFc9A1629106d7a61": 0.005687826434418404, + "0xeeD671a75689E7aFda9F658c8482B0939bEE2d34": 0.005921680626870891, + "0xd957f2298bEFD78E946643602fe04509f45Bd5bA": 0.005932279455866212, + "0x73A5db333D383155D2E4fC506c2802B557108E51": 0.006663016424817614, + "0xbe8bD46D8847a8319261F6Fa137156671dF68982": 0.006675568709055978, + "0xC0867A1D3deAd93c0E79Ea3fD54422671BaAbF37": 0.006687554699576087, + "0x668D123f7AaB549301D9444E582Ee4ccd379C4f9": 0.006572788355387913, + "0x4d237f8E3364Ac5104765d287cDDFbD52b3C621f": 0.006538312189762238, + "0x98EA9cC7128004b6b09D0fF7F922cCF51D6869CE": 0.006532166308293345, + "0xBFBcD879dd913255B32100a72A581C963e7b0ADC": 0.006735215205411525, + "0xe14B7Bcb3A2A9b2EeA0a53dCE0A60F1649660C4e": 0.006633256788515716, + "0x468876cB9b5850359609Bb4Ec7977a3f41AfdF75": 0.004443382914403761, + "0xB3983fd5997711935dC61118e684DDCA1CE3F8C7": 0.006668200575709332, + "0x7c05dE20A59b43c0Fe27eA1B85A2872E9EA519dE": 0.005947940502687823, + "0x83CDb49eBa3bC99AE57F5abE9c6cE9D601Ea744A": 0.004353570686752218, + "0x78d964e9629fD6104F8F13d0DEC2485Bc1a43A2d": 0.00521923721146877, + "0xe36b79317a75b08384c33D21197c7e3273886873": 0.00430200705068173, + "0x64dbcD6e381a4833049cAFB83eb6f441349B2F48": 0.004371506446181522, + "0xE82C23a1084a4fB27ED46628c40301c0f63F0C40": 0.004294972122508976, + "0x68Ba3e38585941E2aBEc12e18c6AC11E15052292": 0.004343138322011588, + "0x52A11a19528DE46078fe1118aD45540A5ee514bd": 0.004421269918546241, + "0x36Ba943373FdE856457511ef8E8955323174331c": 0.004631900172577727, + "0x07f88CeD359895Ef9CE4b3A09746954e7eDFf139": 0.004044142205093381, + "0xb397dEe549E3FDF24C82b72707cb6FcD849d214f": 0.005363492841424741, + "0xf5bE8850b5758acCaD467dA86119Db517b8CDe0f": 0.00477870674359172, + "0x75F223915302B9bA12eD8F5425f88b74379bE6aD": 0.005633177330600567, + "0x0914Bf3e3DB541a79f6587F83A921Eaa368CAeA3": 0.005515535037250895, + "0x342F40FC637e631f669a5b38fA4fc94Dcdd7DBED": 0.004856730287315828, + "0x81864365b031c138Cb6a7c64526C7357fE4FFA2D": 0.004725823291706761, + "0xA40ee0717533dE5b87D6f2054AEE815B8461126a": 0.005540891065201492, + "0x205a89902311Bb2c44668d5712D7a21781279150": 0.0055963795237416, + "0x1f63E3125AE5b76240954F78dF62b4684CD88c25": 0.00533871007710764, + "0xbB6aDdBC9C95100792Fd80FEE1cfB46881DE84b7": 0.004939866587429338, + "0xa4bA32A41A317b970c4ADFE1e1573930c2B4551F": 0.00518646666406166, + "0xa4c8e8D8983e53381b25967659A368f8E108aca2": 0.005221459628093751, + "0x463bECEc49d10Dc785110031B9F6AfFbb84b6aAE": 0.005001842248096382, + "0x883Bb7134b7f5673b08fb8d3c31814B55bec3a43": 0.005302389397632659, + "0x212df1ED15FB55607f180b8E26dA4A3db66b04d8": 0.005260793646164387, + "0x6B56fAecE16358B3e63b231837963465cB98A152": 0.005359986828296686, + "0xcB4E72E300390B3E352f20787300CB741fCDE09E": 0.005193032592415696, + "0xC03808e0Af01563A739e408268d5517Dd7d710f3": 0.004002533158707488, + "0x853E5f1A139FdEa47273A4632c70368d095070Cf": 0.005389811575444142, + "0xD27122760634f46994815A2B5097FFF7b0e910D5": 0.005383091069175617, + "0x3FB7d3E1212cee588b14E57aE9A50eD93eCa0580": 0.005505521926430484, + "0x4Dfe8442Ad63763E7D143BBB40F6A9A76F86a551": 0.005634015534023233, + "0x614C52345D9a2542460a765B7332016BA73599e2": 0.005281110044509529, + "0xe2A85879BE19fF727cDB79Bbee733b616e7c338d": 0.005740303551728955, + "0xDcdc4E48c3DA83109322E3fC507181D65687Ef84": 0.005670139506604261, + "0x3Dc3862Ba073D508e421671c7F44e9Ee5d6B33CE": 0.005453079881449804, + "0xA7e781E2EA7740177d9b9E13Dd2134A103f5833b": 0.005493854028064923, + "0x8d3450C45C789Cbb6E03baF1f939B8081ea41Ccd": 0.005535368590127715, + "0xfAEF14B594cae1666846daB2780E964df8557950": 0.005564433145059939, + "0x6FeC2026e8E468825ED243445508f1bD1215059c": 0.005539950978392001, + "0x677350145860d4937CC04bbD29333C321862Cd19": 0.005493071023694478, + "0x816a7FdeAA4B1Fd5CaCdD337d0A815347a5E714a": 0.005555053317490196, + "0x49b3fB1B5E6C6Ae2A0F15dE68F73F9e5Cf99Bd78": 0.004626840366089316, + "0x0024A67e0b91131d6978e1e0f72c94497bDBCc35": 0.005600765948008375, + "0x62a3e17519aBCE8b5B12A92f3E01bB6b5CB09751": 0.006032658412792359, + "0xa394d3bD4416380cC3498af7d764fe1Cf76A69C2": 0.005701968614075017, + "0xabe5B6e8a4e79e7F27DB3a6d9E6A6f05e521f604": 0.005095168603842348, + "0xCfc1D59675355d5288C982d23caF28a2D0A6d48e": 0.005044485721991727, + "0x402bED71F1B26a068664C12818ed721E37155A44": 0.004812745769547244, + "0xf2009F3E705e48cD9E1d29397fc19Fd7E4870cBF": 0.005301933452011063, + "0x089773A760FEE0F1A3D3ECfADf4b2E145FD1E88f": 0.00495786188699351, + "0xFcECa6193031F7f1336Fa055edFe96555644Dce8": 0.004971683183150744, + "0x12abC23621Bc6a6217c8190Efc21Bce9e0cad459": 0.004870139260861977, + "0x7645e40EF215f9Bc44F384a0418c87024646e489": 0.005290437325327438, + "0xfb4d1d353f95e477235611ed67076E61643B5614": 0.004906351130994589, + "0x948F052C6Ecb37aBf9f81b87c620Bb272E422155": 0.005305211090559804, + "0xBE71d84a622010A0C9709a443017FA53419706f5": 0.005207550423374617, + "0xdf9Bd257d55271851b8F75613542635Fc608CFc2": 0.00506495634922846, + "0x999EA3182C60ae6F58817C77Da6A769f6f731f34": 0.005127794622620582, + "0xdB040b1bAD2941e02F6fea3a7f4a13D189E0beC4": 0.005074182836323011, + "0xD7D00580798FA514bbe9b71F3B84209f83Ad5bE9": 0.005347684918738164, + "0x41DeB171107fBdBb7290eB4a8E77142c4636C13A": 0.005437636712607175, + "0x32a27a34B002aDE54C21515f77593E2086f5E7d0": 0.005336062322419466, + "0xE08A026bAaC28a95041DB74Ba78CE93Fb6aC766b": 0.003794713788955755, + "0x78044a54e9009eEE6aba5A9418EA6380f153a7c5": 0.0053075031108143, + "0xFEAB4fFA81BCd17dFdC2d7e906662527697915d4": 0.004304830841179797, + "0xea03Af40FA59Ac9C311187Da0f9b979DA073C226": 0.005381808647131431, + "0xbf72eE28dc8627AD3e76bdA841247EB39837806F": 0.005392191575261658, + "0x3E59864442ff8e0043b5360Cb134F6Ca2d514152": 0.005414648800851833, + "0x90bd7028416753B38714F32acdE927aCBFD7D18B": 0.005374026721898599, + "0x42a786c945032Dd0AFaa89fECB659789b56B3FfC": 0.005401406382736322, + "0x60307A482765634C9fdb773fCF4066bf8614df8B": 0.005497653443793023, + "0xF45E1A95ABCa5362844634106a1B0705CcCcfA23": 0.005396310953439998, + "0x64F86C703002b9fB260C2fC65C15ca0e65530fd1": 0.005764888059829446, + "0x0013Fec13D8e4bd86AF7a988087B697ca1057B88": 0.005499165077554501, + "0x5eb31519474Aa90E492168a403Fc2AB4522ADc7b": 0.00562459036098475, + "0x9C9A11a94f95cd31c06E0252eD0cE908b90FBc0C": 0.002870512351599045, + "0x9301580990202CA724E2d2d3F2Cde88fF50735c1": 0.005312936452551517, + "0x60CACe9B90E3A1E6e49b1EB16BdA5fA631cf23A4": 0.005291236654268062, + "0xb93EFD0e79b769D2b3Df7aa64d89F983D2fd02FC": 0.002876305648442473, + "0x4Ed43703F882CcAC37897Cd46c80e0462be5C91B": 0.004650083986443426, + "0x2C281042A8dc2699e4e2BcDac11c2810dd40d8Ff": 0.004652223577932017, + "0xC41A3d9ED9DD925fB057b7C1599249CDB4C6B66b": 0.004623126507754498, + "0x5e4180eADCD9328c0dbFBDAFcFfa73c8eF831Ffa": 0.004640151547096503, + "0xBC46980A01D8301D336fbf9377aAe711d34fF122": 0.004389956349494256, + "0x2a9437DE0cCD4FD7b7D98831213AcedeFC7a1092": 0.004871026047528614, + "0x32006a2557954336E877Db126A25e4ac27897C86": 0.004603552051164762, + "0x841499f8F5F869c20886D581641DC181E9C6B672": 0.00456456263804933, + "0x58504a178E3A3B8B65E51a9014679550f1dC5a86": 0.004561726202558048, + "0x72e1260FFa7e3e7F41eff646B24694F8c139c73d": 0.004564226937674648, + "0x610C6f79839DDA54E8a587e279E6e93a0BF589c8": 0.00469294255861764, + "0xC5c90045A5D097625634C7d4bb7dBfBb8E3310AB": 0.004679624495968303, + "0xc0FdAbeF949f28332f596e66eE8e06a13A103c02": 0.004732603249986655, + "0xB6e74e6fD559f9207679D128ddDBb35B9042A166": 0.004641311099193408, + "0xc73f65Ea9d3d3c165cC6Bf31dE607cb946B1e4C6": 0.004615798265129571, + "0x37b9171eF596Ac6A57c1d2598D71345e2206A5E3": 0.004475218944630909, + "0x59760d82C6c5B6B6F8865093820B74B5325d775f": 0.004489253938862162, + "0x2dB601b85292C8c94E87BAc3e56B3fD19CA45063": 0.004504406397440558, + "0xa33f0D43b87dDD418C029412b6dFcFA8a9C68074": 0.003702325791209894, + "0x4A2e4FD85Dfe564C5b14A134AcdFcD531a5BdB92": 0.003830320280251779, + "0xc92f8051ae3786fe90CA5aB89361DAD6730c4Eee": 0.003760285516173553, + "0x73fcB73D180D013ae1dbE306DFcD59C5Ff01b66a": 0.003762107937875285, + "0xB09080C5aC5adC483208DfBE22f8684eEc907c17": 0.003242510428529601, + "0x4241A9998720cacB5902cF887A5323Bb316E3166": 0.003795465605688354, + "0x422Db8FD3778343B595762417b62474919eFeD41": 0.003942407679586561, + "0xDbD9416f32c409b3c7A29655AA515bd717616470": 0.007179857406462705, + "0x126db3213b309A8D554594e591e614425cCaC78e": 0.003536337582191735, + "0xCb8c77837f470053F91E1e288CAc223118C69937": 0.002617483593569277, + "0x8bd7B5E860998607715Da42944cc9DE3486A3Ae2": 0.002589372039896734, + "0x336B9DE28D67D692C31DF93A9b8630B2Fa50d88f": 0.005560030107702739, + "0x393950505b160607F40D11AB956C9406DBe6e4ce": 0.004061734561030877, + "0xF055cbe9B6b30D64AC1D7305cde7BA6c0993C86a": 0.002969448155256594, + "0xB73812cCE6F5cB7ada40A134b4b16AefbDbB9472": 0.00304555917028695, + "0x803E38C54240244046545B421FfFE4e05BCD5D0B": 0.002246137387203854, + "0x0dD7762E2fe09c9eE2F5aCdeA19C102f7c16D8C2": 0.004166805588200482, + "0xDB4D5A3e683dF965CE509ef191d979e77543bB4D": 0.003106416179876122, + "0xA432B3e56A6F4dA4574cDF2f27bea9bbb5543011": 0.00199016501243102, + "0x37c5db6F455F1CB3274ebE67582C92d04C4f6545": 0.005870668349717188, + "0xa85160a81da205AE57F6d55F16C9C43d773c7438": 0.004192670454815279, + "0x49BA7fC7a31b6d49e0C7eDcFF76C1678078EC8F2": 0.004988593293695316, + "0x7BAa3b328603535006d76D7B80aF7260FD8A946a": 0.00215459132153073, + "0xa37023933715Ae766f38689a75a525f351c50C1a": 0.005140864305682447, + "0x3b9fFD4CeFFd768DF16d79e7492A1BFfD087C44f": 0.003717455147054152, + "0x83f7321a05876f0bF973bEc3033858bb0b91e37f": 0.004947772314360344, + "0x9F9a6867d9Ed4630DAC6d3F9C125248600DF03BE": 0.002243052461750048, + "0x10282beB038378EF5cD112c0e1acAA4209F0CD16": 0.004776214963281492, + "0xa02B48ce476ADe8A3f635857dCaF9475F79AD6EB": 0.002578308390360316, + "0x9a0705ab1Cb8C5139171911cF0a689DA2F54830d": 0.003667776734837791, + "0x379570ffA1A60790A8B5955cf643F868D6ad4c9E": 0.001678675285120255, + "0x02153ebE18bc66C57E540423E69A881a70823d40": 0.004319323268242828, + "0xB8C8D5Ca07C82e7E4c73f0cE93E2a7dD08956cb2": 0.002536305176571131, + "0x3c56D7BB7b81282a369920F4816D75eFfc549b33": 0.001143107656752842, + "0x82074547555355BbE037e0E504d0D0C08EC4dBEA": 0.003602992025826951, + "0x1D1C0E8394e6619Bf75C0F2e9321B3D324409283": 0.002172375206352455, + "0xd48010De315e10D071853b1466f0C273e766FA07": 0.003711115924977541, + "0x47A40A367b3298BE3da3BdE3994c5342e26f368b": 0.006146122641611931, + "0x35A7f9DB799649908688826E06CA754Ea0153724": 0.003146540095799597, + "0x9247154eB39429505f75096d5A6be52acE076A81": 0.002986541200407888, + "0x56719d9844bb7968941fe7942462Fc38D7448896": 0.001686027324532591, + "0x0f8fe8e8B7Ad38615904a08e821E875fa19d8b67": 0.002947517151944078, + "0x62A1Ac16f4Bc32Ea0B65795031E75419a46F8F01": 0.00511753971684709, + "0x587Cf3Ea6bdDB04A5C6912AC95120443f4474115": 0.003897619221527627, + "0x8dB0696b0835031ee2166F130d90Fd31EfacA4E3": 0.003488149878811912, + "0xBB323229972D001bbF725b3fB3734eE53B7455CC": 0.003232179668996353, + "0x05C6A4dA04bE965B659aF1365314bCade309bB82": 0.001829503139378177, + "0x5002a9263908CAb85BB4c71559227647F82530e8": 0.003466039557595452, + "0x78be141970C8378Ff7E14dc0E817Cb17b342F5e4": 0.002212149700427305, + "0x44C642f69a39F1b2b788C013c3839277cBb24DF5": 0.003836735948709853, + "0xC8d23C39c8F808D599b65D4C9eED01B8580a66bE": 0.003210725538821802, + "0xa3C18bAe51Dfd07FA152492d685c457D0fEE09D7": 0.003786815683053574, + "0x345B46fCF8E503AE3b89174a59C04D2D212A5a10": 0.002827601077960414, + "0xC5E789964681a9ACf7D8C84EE89252Ad531E6C8C": 0.003510703733783151, + "0x467c3C9D910fF352c7472571d3360bcE53c2F6B9": 0.003686907980382298, + "0xf611B9A9F0d9a0DF279665b05fE338b29d53744a": 0.003446501388391612, + "0xE30C4Bffc186667d5dA5EEfB505B419432c62168": 0.005179056118312352, + "0xD8c50C68066eFE49bC12658A5D7C984E7254D417": 0.003262182767589676, + "0x8a74781B294238d74f86B0cDfD4eE7b1dBE55d7D": 0.002588713548216432, + "0x8903349C5B3205Ceb9D004A051DB554f70D1Fc62": 0.004246383322666131, + "0xF5C14eE163B349ccC50eBe31500078f745500580": 0.000384371708035421, + "0x1FA1C17dc5dAA02730b97B7a9b9D75710244d98e": 0.003217165390280769, + "0x30b2DAEb3757B6C7462cd0D776828F8d7398BE50": 0.002119976570762638, + "0x9b5d6a05E969f58438780d775C0037884526877f": 0.004466254400746654, + "0x744c2f5FadbC305d20Fc91274b71a6896d294946": 0.001617345276729899, + "0x5381B78AB971afD2ecd44F1431D635541aca696f": 0.00249527210958292, + "0x57fDd988547aEFA02dDaAE980AAfF0B031924D3E": 0.003746349148734648, + "0x1bA4b6B2e5864838ed336495eCE7f456b1ba1FBB": 0.003012032167256555, + "0xC92b2aF1B472D39275181f502b9d369ad9507DbF": 0.001724610077863405, + "0x20271eC8650e0990201EC5c785a5f3E8b51850ff": 0.001783229495299448, + "0xC5b1624c0aFad0E366A9cDF80C08C3ff8253710e": 0.003824565620911651, + "0x94d0f3A10f88A63fcE0F2304ed63D3d166fdB313": 0.006951786579609752, + "0x7ab3c28958844A758FFA564F09c73dDa7Ffc766d": 0.002794809103149954, + "0xa7A56D141C552cfB45b4AF6aBFF0aB76f9369c28": 0.0030855561334636, + "0xb187ba422872C0467390155826e5290Fcc9fa3Df": 0.004522298213792397, + "0xc56d5742F3DcfB9Ee9aCBf8d86385B61b1F0bB33": 0.004664617151120784, + "0x6E99c76778B44b430d5dAc1559e7AA9DD76dDac3": 0.005255874752206521, + "0xe2A2f2A338EB923454e331422e9b6ef872325Bb5": 0.00219930939644837, + "0x636223B012C4d186153CDDd584F3f4F733257Df9": 0.002296721242856748, + "0xb36268588ED030B4d8FbB22a0B4ECbad1194e683": 0.002637203135996779, + "0x43E6887aFcF79DbB6aD9c0B22f802B77fd7c6404": 0.002837284257477916, + "0x64125D5e793b05F0290e4d322a5b05Fdd3EC2674": 0.002275345217599607, + "0x94478F8B27CeDD6177E238F48164A45245C854C1": 0.002272857970108901, + "0x58706B388caA1D46091F1FE4559F6BC77402B44C": 0.002139083055491548, + "0x48d26F8F052d80E943694360899C4bB83344FdBC": 0.002140947931523132, + "0xDcb26b5dBB5F8798C1b434597ffa5e4aEca20d05": 0.001700719601739858, + "0x94667C16eF36c34d6De71FfCE6E80C5d24672a41": 0.003863780104982716, + "0x50d26FCb38a279043bA075B86df912Cd523931Ef": 0.003921599520197681, + "0xd2Ad096Ed0757dc4954f66765dea737e5a687dfF": 0.001932313638441132, + "0x4C7D5a6437B325A998f83d9dcC267c5fdfF8ef56": 0.001883933259861015, + "0xFB364E4D8eF3bf2551550DF01e0c8d55D3A772EB": 0.002498442464865746, + "0x0b0221d279026aC38eec4e13408BA7966Afb9FEe": 0.002356765112319295, + "0xBe815fD2CBF30D07b804d643FbEEd27b8E663acB": 0.005725244398097888, + "0x967bE9835Ca02EDf7A8c7dfE26519763c1611277": 0.001955713429192355, + "0xA65EE589b0353e7cd63c03FD534bEa61C748c3c6": 0.002573236495707295, + "0x66A93EA89C257a03a125188f8eB742972537bA85": 0.003838464957193687, + "0x0894f897CE9b108cDB97C239e4f96C407a248e92": 0.003933982146107948, + "0xaD82CC9A78F2cf917E56e6305A01424b9107EC43": 0.004437466573438736, + "0x00B64e31a3C6f59b2120b50b8741584f024722C7": 0.002550435777343664, + "0xb67a6E67072025C1db86e552dc17f7Bf9C296122": 0.003177983613237017, + "0x73cDE0e4F0480EA6B98Bfa292Ea936685716af4D": 0.003198224248243898, + "0xFd0Be09AAADaAb67523e8c6a9A3c1D657aCB2B5A": 0.003304680038504081, + "0x76cC155EEE2e97A34AC53e8b89fc44690Da753a0": 0.003759064640715826, + "0xa8AD81A7f78a55E02f6267F2568e96445fa2A469": 0.00312943685336956, + "0x36Ce63c738971B948Cf0Afb842b7617254C15BC0": 0.003295671787352161, + "0x21a27324B609e864882778c703FFc42Cc05daC40": 0.002517019648617631, + "0x90b979c9E90EC5D5246dAE6BE32ACC451edD2464": 0.002152560700236657, + "0xFec5287823f5a317AB879eF8F8901Ad21c7D915c": 0.002712006573854954, + "0x517E758fb4095a1D250D084eAF16DDd041577A05": 0.002369671458565811, + "0x7c9c7bB3D6880F0d720fEb4fA6164Bd3E49F76ED": 0.002619002571746022, + "0x5Bb7e188594870CE0296CC083aC74C35B2565709": 0.004655384866566131, + "0xd5769DCBa4D94716e860431Be65c0c84C379fFD3": 0.003775233182285399, + "0x8594E5a6f67cB13CF525EA15f2e1FaC3EeF63304": 0.003171870172426085, + "0xFC2ed2462f05608b6a21cf1A43bf24a6Ea08c4CD": 0.002011138765708628, + "0xDCFCAEa66D61Ac1B52bcFB647c03f56c0bbCAa28": 0.001880069362935232, + "0x5A7c9e40Dd0b4173d368c3A810E5fef2E92F73a4": 0.003132827280912697, + "0x9Be6FcbF8d76201559627BaA8B0cD60cE7e06b0b": 0.002910129199110819, + "0x6fDc3F38B32fF607199B7ba12459D741CA6f4357": 0.003436278467532854, + "0xe251B115E89036C0bc0a8Ff09B36f77ef6291D84": 0.001963913475454665, + "0x765C6299ead6a2fa713E0D323Ac6BDc96bEF214E": 0.002553810228253602, + "0x6990d1288EF65F0d0AD9E2c54d1ABc91118C64ee": 0.005533745291526558, + "0xac2c2C3fd735c5DB2aB77D8358DaeE705932ff3C": 0.004988486242051986, + "0x461980B8560EAC362aE5E685cB5a35952714611B": 0.003452972528611829, + "0x3A4a969169aEbAb4e9AC667C9aAC62DC54c53A1b": 0.002420907220760989, + "0xEC67006aC513BF20ac599B48f1f9F725C142BB23": 0.006445193220532985, + "0x0CB8dA6C265a90B3CCE8431267c0A94a7f1db875": 0.002531938733744669, + "0x083083Dc8dE34B1dB09910ebC8a8Ff7a47C546ce": 0.002600793639924626, + "0x16D12711626310b5894783ca187BdAfe7aa4597A": 0.000851230595553245, + "0xfBe0f4B3939701f2d69a0511490Bf56c5869966b": 0.000635338319607872, + "0x18fEe6e511646B8ea2e4964277574F637Bc03f3b": 0.003104084834065576, + "0x0581277520d4ddd1561FD970C0A66b1a6c7748F4": 0.000625291677426801, + "0x9687F546B8867607E3b74D6727699C00c8970d7F": 0.000666504357931096, + "0xd0A530121747B005af6Bed69426092cB525713d5": 0.002667038917825165, + "0xD25f7e77386F9f797b64E878A3D060956de99163": 0.004288708365846, + "0x8d47CD9B8b015B0F3865e8eE0b96b8125bb1F483": 0.002257394493615256, + "0xAb16CB03572F0459DDB1aFdA1987fad468e248F8": 0.000679842900604685, + "0x6C9b8Ba06E2212D29561A5910f418a042fC788ac": 0.000220895937252681, + "0x94C09Ca26ba1D974Db8Bd84B6eDbd2f576283E7b": 0.00035034089203452, + "0x3259ab6D2a237F9F2D2B2027252d97dfd5f5DfC0": 0.000014904979778654, + "0x9BC114CbDf47021f15416e720bC71b5341120E87": 0.003778577936847616, + "0x3F08eE117168Fd5E69cecF9a843c99e80d04f4CE": 0.001130283624874802, + "0x61A0AABD648569727c53735F2A8AcE7280975753": 0.000443725292078629, + "0x2108a6d1f32D1A932431d64E3328D1d45bD0520f": 0.004257360434151636, + "0xD225626025F48Cd43cb35CE935a4F4B856AEd21b": 0.002320106686700792, + "0x099aF188E9c68B91617EfE4b09Ee8CD90ba4c63d": 0.006856525945082547, + "0xe0b343b462aB6D0d3048644D1a85f287D46FC23d": 0.0036223083230886, + "0x9A4B6F0839637769e14DdFC03D4E7c537d8e25Bf": 0.003173272548750979, + "0xA33c3B5Bd387B26F72E1c5e76bc1bb81e7935EE7": 0.003697228995807725, + "0xA6A162FA210411Ef494feAAD1605c415f8fe0da6": 0.003565423053234897, + "0xc9B1B3Ad7546703a9AcfE2940287ae7F9CCAAB70": 0.003226475071972548, + "0x410fCF90a3805DFba3939827b0E75bD5fc2ef8B3": 0.003157675747601367, + "0x57b92dfC53d2D50135946b74C02f0E8c472A2f11": 0.003132128269899298, + "0x132DA096d35f9DeA0FD7F348232582DA4e551dA0": 0.003173731762727495, + "0x4442dD25DA06786c78d8874fB33381E706877FeB": 0.003144260830292323, + "0xEBac3e24c3f59d50a713F2c79535acd381487486": 0.004303946677137283, + "0x686c4D2ce918805D05FD93F109e279b0c3DC8Bfd": 0.00365487562716427, + "0xFfdBD837ADAe8558684111d4B5cf9Ca36F58569f": 0.00436046866711217, + "0x4cFE0198958D72546c4F8E415616B4594DF18679": 0.003702362544028557, + "0x8891E7796d54cF5b801F0A01966be79d7cC2a89A": 0.003652105853991808, + "0x920309B57d9292F743A214c14eF7468b63EA8D04": 0.001658264424770377, + "0xCBcbDaa4209c955A79CD555C47a7501f10aA44aB": 0.001251634861955057, + "0x5108358B0309aDF9C3a298530f761c9380e004DC": 0.000759675205862542, + "0xE154fb66fed34faFBF94Bfb5357fCE857C70Bb23": 0.000217430098425861, + "0xC87e43DbFEd879Ae5A0806d9CE7e6fDA27a1C6Ce": 0.000136587833187373, + "0x03Ff81590542dDFd10B9b91139ee943de62ea1A5": 0.001352212478924385, + "0x2EC20e5aA17F736060356f6B186208D5Ce0aB4b4": 0.002792287620595303, + "0xfD8355b24aB8815cA2d76d1E495DC29B4330241f": 0.004317263749998068, + "0x54B74D49cbfb92343E4607F260BE721b208b4dfB": 0.002640279824987559, + "0x8C386C860C757A44696D276B42a997FDf0cE1BB2": 0.001247025536983943, + "0xcA64E575083e0a8f9C73Ffc214D78027d98FC51b": 0.002815201498319254, + "0xBB68400DaA7AE42392DE56026F9b5c1E6F923e3c": 0.002958889681551051, + "0x8E5FDb6A37f2389fa638b2E144809C7d7bc21E4A": 0.003045728328233854, + "0x50229CB8317ECF297E65cdDBCe88e0814eecdf9E": 0.001973190408827668, + "0x48767f20ec0aCA7f47b3dA2Cc32Bc06549470A9B": 0.002711760155859556, + "0x484637541D68ec3627Ae6E2bD7192E167b88E93C": 0.002506138624102778, + "0xd273f87e43851Fa7f0518E3B385c0d964621E3c6": 0.002820057629910732, + "0x9CF0Ea03C7e23f2C466d48f6BfA14A85EF7CF4c8": 0.002778056841583459, + "0x6Bdb3A8ae008cE1d3073870c852010E089FE6753": 0.002004908539294976, + "0x15856FdCA72b0429E6E2117b7675dC2b0E6272a7": 0.00327954207522005, + "0x094F5F0706DB7e3715a87Bc37437f2E6e6029B3c": 0.003654033433996635, + "0x2f55877D6D8A42BD87e0325201cD15d63aBf5866": 0.002694380152999028, + "0x69D0341d380a1229f4751a0A721345dBc716586C": 0.002576275160788964, + "0x8Cf35646c42DA86292aBDCf64bd0f7e7fC644a1c": 0.001901533669788742, + "0xc0Dc4010e76fbD53C82b19f8f8d7604e37289fB4": 0.002646698521216856, + "0x4010650464cc07e447ae10d3135F8c82554b2528": 0.002425950323316673, + "0xaFD255f71cEBa0c0EceE10fa52F3e2fbeCcE95C4": 0.002739967461690959, + "0x40bFe49745Df251fA0Ac7a3f983101FF170c389b": 0.002533563971520698, + "0x5060020e66031c324f77ae24F14Cfcea6A688Cb7": 0.002463119550065608, + "0x574Ce8Eb2f3BDC44Beb64eAA9e629004276586d7": 0.003643416040915074, + "0x1EdB50d83f76382480886597A3023fC318B2ca66": 0.002554595239784685, + "0x415106767827A7856D826458a486a87e0e15097C": 0.00255601976500171, + "0x48A384D082C97f82ABDaC55e43EE8f2392b9f394": 0.002424311295329463, + "0x2EA989edfCac6531cd912d09A456f9809BaA5377": 0.001977773331475094, + "0x7cA4b00a3aEc07F978D127E69bC16484a038619C": 0.002542910433504229, + "0xdd877AE95f4aD48b4Dc640F52E802BcBE3301130": 0.002953392918814504, + "0x590a8DaE6861CDc2b0300096ec6E4dc6cF2143F6": 0.002545196306055699, + "0xb916A83cC28F6f63ca9807AD3bFa84d9e14DF963": 0.003689030824548457, + "0x3b84E3FFBe845c0349E258f243B5F00cA22Ba587": 0.002619480646531541, + "0x49135912edB24205E1b0E7b9eA71887edC59D50a": 0.002473758553609714, + "0x81502de049CE028C2A91e9c91d059Ab8Da8Bf469": 0.003704530855868746, + "0xF9D3A0a21eca45C45F9F476Bb4Cb40c1C4f3aF07": 0.002656225632326252, + "0xC590314dE55b52C96eb34eDbC4b55cf8Fc8cD510": 0.002617167118770428, + "0xdE7250D923299e1EcEDc0743b159E95B945082d9": 0.002586865177840114, + "0x6209e6ABfEE4Acb6Cb6C2d5FF8CAA35CD9B87984": 0.003001422492237633, + "0x9EFA7B040eDEC79662F0a7bacddE8bd1db50a8C5": 0.005144935757284119, + "0x114D4348265E8302980e7BA2db441FBF09EC3303": 0.002324231934493377, + "0x7975ae9ACd918f2c2F77a365e9077d098A102C86": 0.00190635524304107, + "0xb4C907afdA8C362B58281B5c43A2e7b79f089D09": 0.00262120448758911, + "0x6748445D83259a6709e459873323324a54072d1B": 0.002667236763985175, + "0x3Bd0cbC96186Cc3eafB304111e6Ad20a4Ac92F8E": 0.002660320642376976, + "0x630A63523A4f079201fb548114695d8da1d742F5": 0.002556083433326372, + "0x6B8F4dC1D7D243a9f9b506D58020c866EB199885": 0.003121566826163681, + "0x0788f0420961aE4806fc4Cba0898A9ca0300eFC0": 0.00330082632512012, + "0x26fd27a26a6C1EdE36214512ee4E56440a0cEbF5": 0.002715834723040444, + "0xd1Cd2FD35C63e27A33f0b5ECf9C92ba1AB9c6dF1": 0.002599877268944664, + "0x76bd993BD4A08FE154690095Ec0a3DBb51a0eb08": 0.002164798895388511, + "0xD8C3cd1A7576efC723357B7158318f0CeE0e30F6": 0.002520000915424015, + "0xf882F94D9fA5a7bb883D3Dfa04e5A43Fa057C333": 0.003118627682909301, + "0x216bf62B05246bf4a1694061E8769464A6BFD812": 0.002690726115600343, + "0xa5D2817A0d9547af625942E6F3a3bEF71E5f5Dae": 0.002442304466675559, + "0x28cCfB369Fb97929068Cd30A390D37fee0037C61": 0.002681694089661293, + "0x5d2150E5d88A30d5793c6C49959B8f7d350a36A5": 0.002666873109622147, + "0xC4E70E97A54bbf4f9796099282fA47397da4b4D9": 0.002682389669768488, + "0xE7Ff7aD54492A38AfB99bb5d8B897C5f93A66f47": 0.002718011374425757, + "0x1f12254be217Cf9E9BE46960c36970390b07f16E": 0.002665963118134827, + "0x1D463047F4c954D70d2718AdF96c43f24aC19dEe": 0.001977637531342599, + "0xc42851d834037cA1f82668596233DcA69654867C": 0.002554714849151159, + "0xeC2Bae309d0A18D7dDfD4EA0f17a2f60817f4E9c": 0.002528146455438507, + "0xa3638f8044d928b42dD74085284bED980b0e0278": 0.004445550134723651, + "0x005CDb3B0B0964569ce0aCbEF483443296cE704B": 0.002589627288954021, + "0x1E1486d4c30fA85E7fD5AD87cC7DcA15a626374D": 0.002798976509119085, + "0x6137A7c745CE7ed7a6eC8cA4AA5B635fF17d5467": 0.002098827643268694, + "0xB8B5caDA2A1Ab13f421870555F99887e3d6A2e77": 0.003820319682833393, + "0x4A6115D5ee87a3Db90b47881B7d6e29802DEe62c": 0.003310714050952304, + "0x6B7d0041B1B05f1D8f86AE923Ec09557e32Aa416": 0.003626715410476723, + "0xfA8cE8D44271201e9Ce37838ccb75BA482d597F6": 0.002007533421729204, + "0x4289C656B76B20eBF1B5Fa4363dA812346919bdC": 0.002038070087926596, + "0x4AF80E6414EfeD0B91FA19c0D19B46C381beCB7c": 0.002037856562594494, + "0x27b7A1b3c4A872FB30cF22e8716596a2312CFD2d": 0.004235101306215486, + "0x074F2CCfB2716fC8B6aC579173f1aAeB1f759d52": 0.004785173381623691, + "0x54d6390e19Ce818209bD3B53a5d0D2E0c6FaAe04": 0.002052600980301082, + "0x4241b7A1b190F97213cc092237833305af62f563": 0.002155273358632809, + "0x8b1728Bb25502476d16CdCF0861669f68c91A9d4": 0.003520425821590466, + "0x22B95B36a3f4a7dC952765f9CC110ab455Ff6E4D": 0.002386895425693269, + "0x2F966072f36109F27539E5EdEfA741912206E491": 0.002101892455936313, + "0xA4635d0D583F6A5335Aa3CE39CA7D7c2e7a7D01C": 0.002050051774288798, + "0x58CFC8ee2132847AfcDc67CdeFA92b2D21eB5Ba9": 0.002021451992854978, + "0xE86A48bC1D340Bc524d5529222F5b51995bb8132": 0.004089794668596579, + "0x09C1579AAE05524f455AC4852d60C3e973ad0715": 0.003291777955967139, + "0x295c5B0C1D5acEa1A94eDcd67005aec356ad1c7E": 0.002534350149740295, + "0xF3C162C189341D024ee753223101612ABF6fCf9c": 0.002001832539932383, + "0x09a10823b87Aed0A3c348C0a20d69d3276192913": 0.001966999594675864, + "0x336701baB9Ee6a829a5d610A301E978ACed202C4": 0.001958711206166663, + "0x3895799b03759423C728Eed3aa0C0414F5179f79": 0.002000557844595742, + "0x5BC3D8339754B5D4455355B3C5CF2639fB943942": 0.001978992583726762, + "0xC0Afc9BaEcE062D4cDbbb56eFBe33BBd827e560d": 0.001807072968060103, + "0xDb6D77A78b4da7286E3C1A6828EB83D9F0cCA527": 0.00202145806771611, + "0x9cDf01F751864333515c209B733501FA5bB14143": 0.001973741681116513, + "0x2d14a06687629C8e0F9fcb985814FcFfb60FD36F": 0.002552662716855585, + "0x76cc3f2Fb3f451BbEeD11bF9F64Bb35f43438829": 0.003184731727829905, + "0x3009e81f3b145c71A409313306Babb0AcC219aDb": 0.002030785515367991, + "0x76e0eEF2E4883f5163ACabBf1C00a8eb73D25d83": 0.00263012121239364, + "0x496cdac4854423c66EB0Da89f9e96Ef9D8312ef8": 0.00196676875334732, + "0xE1d4C898E9720979c898e0962a1d8e3A897f9263": 0.003930500624280352, + "0x8F559d9F555131932345C2A9546df023c54E096F": 0.002033172524715093, + "0xC8a4C0aA604f225aA006835672CCb68e661f7Dbe": 0.00199427393869753, + "0xadEF6E3234cA45D5bc3C2bdDD4bF427862c60335": 0.001953122124475215, + "0x92A5D7978E46759EDbAeF30012E4c60C8DEeE0A7": 0.001923024604048646, + "0x8b992B29e691058a1EDD32378dc11E6480E0eE24": 0.001858179361629006, + "0xaB0Ea94509caa5703362EAaFd8087d205f97a340": 0.001874388756474228, + "0x088887cCa9F1E0a6a4D42BcBD3e107686bda2486": 0.005036375798240871, + "0x3b59d6B33E8F8dDF9734917a40056D07548a4444": 0.001940276267209836, + "0x1098874e7b4435615CAae49AF275B22e195A574f": 0.002125763065034764, + "0x7d822dd2320B0B079db5DFB0b87D63A0E9F090d4": 0.002397940168651098, + "0x929cB3CDB2C23fA479D72c21731C53822f5df881": 0.003931279140301071, + "0x0dFb17299E2b39C63602Ee11BdDf9688Bb66449C": 0.005652637481333481, + "0x419d955a9C3dF6A1b9eB3EbF2d21a3C63A8d57ef": 0.003203588729423946, + "0x5b01ce79D8b3B793DA3Be5e27de3A767f1a02eD2": 0.003712245593064075, + "0x64230Ae13E943e41450061d01f38b606E6dc996F": 0.002127712879790799, + "0x7460B763e92f58f58B80F6650B41F3d2cD10fC3a": 0.004246435194087087, + "0xE19243a27D28a8Aebf138DeaE361b8AB53862a9F": 0.002562877389208267, + "0x0FaD7Fcb19f3EBe9402BF0623d7ed0FC4F1dEf15": 0.003817176065051232, + "0xDEf3560E74E9569d32339337D6A05f3F329D7a3a": 0.003124767350955214, + "0x72CAb6D1Ee9676DA8956A7A8E74EcA4052d19696": 0.003820213956429628, + "0x7d8AEE804Bbad88d0081115Adc917F5d9bF6388C": 0.002769073807377294, + "0xCD779f2e141fbA5A332A8Ae7882Cb1aD86cB8D34": 0.002364594804029965, + "0x5c4907bF26883c8dB9cd38F314bB4DFf710593aC": 0.003531003433811764, + "0xC84FAc7D2F80D70b21A536Fdc1Fde5cb404d747B": 0.002508163061315146, + "0x09cD0D28125587e39a29CF25Ea3f7851C585738f": 0.004268541189130728, + "0x2fbbA6606C7628b749C6814fBAc1f88fEB21aeFd": 0.003189387363726861, + "0x5836Df3DaA6E9B97434F77272a3e8ae3c478D0E7": 0.002152303982127773, + "0x17e2eA46935588BcE435278Dfc4Ffb31F8039BcE": 0.002359992359495997, + "0xaC880a2568c6F5719AD59C8Ea3BC11a910775757": 0.00235031410400374, + "0x04AD0F62A66bf8FfF774676a792E88D10942e2A5": 0.002989985035956111, + "0x340B8E5B52619c0ade021F806348e11274783740": 0.002183008174786425, + "0xf5DF7a18dF35dA5EcFff6D55bcF920e3d8F6d5Ae": 0.002196709878488601, + "0xd65e71C781BDd00221eB77B920298663D0b83484": 0.003758478567937568, + "0xd5E10116D747EFC7028fac192093D2AA2Ba9EF12": 0.003497319409546596, + "0x4D2141b31437E970A0f13c935180194a8C4308C1": 0.004367437087458743, + "0xdAe56179CbaDA38DB0A15da62D43Dc66306f746B": 0.002465910227237082, + "0x41a1F47F710841F2f4cf492149C205725875f400": 0.003004621478195102, + "0x9D3a7C178E38748a3a53BE600C922aD5fC45C0bf": 0.004540126850686812, + "0xaDE8502eC7a7Cfe5fc273cE3B94736BB1F76118A": 0.003022951671570491, + "0x910144b369ed067F8a2ea470ebCC2Fdb31c0dd9F": 0.002636322408178351, + "0x4C9B462e44B14df09912D99Ca7a0daf9fF0d6f77": 0.004806984639279794, + "0x4a194280157860E8aBfB7446Cf9eE84bf66dC839": 0.004115512652888757, + "0x6aEdb6460ABAE82F5ED77aF1d5e9Fe6F701d8c4A": 0.002166841988969728, + "0xCc50808A98AB15312361ab4837f412B2d9cDdA38": 0.003272956796059544, + "0x3800Ebf79fE712781916EDBeDb169bA295dce5fc": 0.00452659971694939, + "0xe67d3b0BDfd1D853FBcE6C0898b464e332a67B18": 0.001396607895521881, + "0x9860D7309039b9A44B1df878Ed4484133a881316": 0.002165499690123165, + "0x20A0fAb3e883852228dC2D54f4fCd4ceB6b6cd68": 0.001376275487426982, + "0x1D98cAEFaB4bb543d98Ec6136E1498c34AF32c85": 0.002561771052364397, + "0x8Cd66785F2A1B5ADc3Cc81177D485A8395Fce2f2": 0.001865020675795902, + "0x99BcEa6bB0403927fB3c038163478D5b42082Fd9": 0.002016095310210855, + "0xAf8A6DA6F3c64E1284FE6F363516E3Df56050B08": 0.000436401362238575, + "0x57c106cD365B436aC4a2Feb8690CC29FB32E8773": 0.002256609401724709, + "0x31C44F5af149d2C9374f6A4d7253d0Fd69b127C9": 0.001820536400810428, + "0xAAfA1bF92688084C3446fDC741c1453379cD72df": 0.001957879508101661, + "0xe98ED74D2AEd7b818FA01A839715A917D1341bC5": 0.001917592307748657, + "0x553E206F3F504c3E02258cdB93614e0115827D1d": 0.001986041145147475, + "0x05ef6560a7c9C2951B35AFea0868382487e9B77F": 0.001573439901866656, + "0xc477F54B5ABBc255f366aC54FD924a896da5e6a3": 0.001818728317146624, + "0x6DeB5c18F9d75d5D8128F8F42cEB225dD234F960": 0.002009802720978134, + "0xe79464c19fe30E6Db25A74aECf65AABeb92A44dC": 0.0015487185247689, + "0xe6b5A31d8bb53D2C769864aC137fe25F4989f1fd": 0.001972094078769946, + "0x1Cd79a62361Ff4AE9CFefdc128A255B1495627Cb": 0.001999404339179976, + "0x00D71C4FA96e518dD54E459114408e7aF9297C15": 0.002746700043310158, + "0x33dfc8Dc28853A4f9FC0ec04BB2B67C6379CcA7f": 0.002129249979808943, + "0xA941ADc6DC04b0cfd17Ffa75329B680C9A1B3eEF": 0.002077217867124509, + "0x454fd6d5FFe4780577ce64e7B17B39BD80158021": 0.002693643635810848, + "0x21681B5fac7Db2d8DD027487FeA9cd28B5c192A9": 0.003526829823315451, + "0x5576023B904E1EBE5c35c7C041bbb2806e890163": 0.00272230263843162, + "0xb020747D162105158f31bB6Fc0B6DfAa66B23EE9": 0.005103691325392743, + "0x0bB9f7c03eb9C1A31C25b3B7E61E2c503c30B81d": 0.002958817961598931, + "0x430C4E68894177ae43F52b4fd643fd2D6c7d2e5F": 0.002937360843354262, + "0x92BDD46aEbA9C2f4b55edDB522382261b62220EA": 0.002999630429267346, + "0xf0b7e13a31eC9D21c05fcD91f71CB82498864D5F": 0.004089692093341936, + "0xCB4bB9D616f27dc84a256b768B4C393fA8010caa": 0.002186377678179385, + "0xC636DA66cfa5c363C4785835069dcAF85ab91feB": 0.001352271441299834, + "0x0Fb0e2fF6739060A811190b94b6D7da786735be0": 0.00166479927018415, + "0x574c891acEdddeB18d112DcE69F87241794307c7": 0.002682690484296484, + "0x67b4329df2274F21429538a1Cd35bF604C35dB59": 0.001483938648010301, + "0xB87000FF076e59EBBfD973008Dd21941Ff9D13b1": 0.002898767154605362, + "0x5EBC1D2809f4DfcA9Cb518EFd2307fDFFC36D55d": 0.003363576903441813, + "0xDA6De31eB28a648884247708385a0B8027E6C4b3": 0.002026353631936751, + "0x5071e6d385f584B5875166563c1670460905ad7B": 0.003156829576390939, + "0x3B7236C911F87fD75315c4Ed44A1D2EEd725Ad14": 0.002388954399412096, + "0xAEf6a3580A365c524A5bC9aabeB2a13c2A1a7B7c": 0.003708403681673741, + "0x981387F73e94a173F9eE05a7906E299F99E23114": 0.003408989298408786, + "0x7643d5cA36aec928C15181F02A4263D9E1FF594B": 0.00192964068021959, + "0x314FDb3cE492ee03a0eb037De01Ef53757C73936": 0.002181402621794273, + "0x9fDB970aEF60007FeE4EA132B5f4EBc376740aEa": 0.00222260714204624, + "0xC3Ac3355B2686Fa503246a92e34D0B7261b39d6B": 0.002979753074865745, + "0xa8B8f0B17Ed13a3663A8E3f169C42464aDddB984": 0.003555858406008006, + "0xcD6DbaC9cFd5b348744640D8ceF05f1B5245e2E0": 0.003151083268048344, + "0xE5E7EB7B5E89866A6D852F55BFE363EFd50D2F19": 0.002903303178698403, + "0x3e1B1A4a8fbA26E80F4678d3eA3AC1DAcA78523e": 0.003155568409768491, + "0xC573dDc59824F248D3688DF0474805F35C2C09c1": 0.00277352693566226, + "0xfb043BBaF380A06c01750ce0a6324e38eD11110c": 0.002237783984279272, + "0xaCB4FA704c4A7092B3373D5c57443ed3261fDD18": 0.00326618240491698, + "0x88330D5c152A3A064b8883ddE2A8a2aa3e4680fb": 0.003517467922463109, + "0x3AbEBE2bFd423dbb6357674476D44E9bD178817d": 0.003478315898821427, + "0x81B73F850A76D405bdd976Db6744D85c65fe9330": 0.003637082909137778, + "0x935eFc16A75a6f0B59fa91CcD21Af633A117f97F": 0.003060323038512247, + "0xdCe31D9b0a5B0E2A40fcdf9A2ad73C3CE2071C15": 0.003087646581520176, + "0x8E561b9823d9BF7067F5F64980aE26b6b9969e77": 0.003285442086067489, + "0x44ec1775ca82b14AC2A09Acdd21824254b2969AD": 0.000605542175512718, + "0x38F855e64542641f9e254f6e527351b55b560C0e": 0.002391779396852634, + "0x3F180F32AeD8C10Ce46065e05185Abc69F1D70B8": 0.003565716521959235, + "0x2b379bFb86e900fE8f3A1434ee79097Aa5b883dc": 0.002901829659276489, + "0xa1df756B063A867bfB3cf1fa611592Aa646bF4A8": 0.002230928701159392, + "0x0Ab373B6D140dCF3919E17D277Ad1Cb818B1EA53": 0.002636506076644926, + "0x3081508f0cD453Dc99Bbda26ab35Edcd785cdd88": 0.002862198736094479, + "0xA89fFd4063866481f3DA231bc2cCf88Def15b642": 0.004079882471459438, + "0xaEd91598B3ad7e4b6Edc0fC2a0D9E16e8D58981b": 0.005113106839669109, + "0x8DE1cdCF6D3aCC777d08e2359Cd4D6Bc72e382a7": 0.002199653475711865, + "0x40602DCAfbeBb5635ede96B2EcB94d534fcB4670": 0.003050495692727057, + "0xb87087bE41D0299e31ee8c274540a8bf15bdc1DC": 0.003641209513084151, + "0x55AabbfA2e5D574F24aF480E181355DC788E0Cc6": 0.003742239695680172, + "0x70a7EACE9F44F3C27832f92Cf5EFF9B7ee3Ed2D4": 0.00174955228653728, + "0x709e49864C46A307e8f383c6B0094062b74c6765": 0.001798314590623845, + "0xF1De794eCF521Ed64bDd4DD55308361511f87990": 0.004349011105702684, + "0x1B0848A69E665eEBA88bb877b67145789d3d8b61": 0.004441651145386749, + "0x094DB477152D5678A0cE5e263C284DFf1052700a": 0.001677863706781292, + "0x792ed5735E87859792f96bE92E98360fd7c76084": 0.001909640591881251, + "0x579fFc05d22484336b803DE2201Ace27A5Ef5e0d": 0.002899251088306765, + "0x4AF5B23Cf8B2EE85Ca974DA6a51fE12bF726Ae6b": 0.001947949815791955, + "0xa3651cadfc97186D5B93A0aD7Ea32C126a794BFF": 0.003502652289395818, + "0x90483C0d08A16058aB7Ec4455B8Be51a30Cc5043": 0.002594844187831048, + "0xd04383c1e5Cc572BDBebBB88a1292F9aCe70007E": 0.003225364918768774, + "0x10D6F9Fee0d48E7db7279AE0139cb5b577bB5516": 0.003256687769931999, + "0xEEEba9f78590f8C05c67b627BB67bAF22Ad9597E": 0.002855219215858088, + "0xF0D9A0C82dCdE0675E2E796f6e25E8aec3e52f12": 0.002171339327925688, + "0x39ad454BAD7d4909137cDAF1193cC847eFA959AC": 0.003150680981891183, + "0xbc45a7315eda040A0e0a53E022b62042a71077D4": 0.001890526998003196, + "0x078352359cBd47652b6aF7dC1c46DA5Ad1378035": 0.002535312888955586, + "0xCda9C44C18c5C83963aeb1681fc4198542650345": 0.001977595136085257, + "0xa21cC0DE85E8c75bB10519872Dd3965ceC351e3A": 0.003137416041444252, + "0xca49ed45A7d23193b0Bd2BE322D4F0C63168b34c": 0.002585369217272161, + "0x22992D673Bacd1a43508294fc00597158a6B5816": 0.001864260239005634, + "0xF7FCAfb56130a2e39bD28e5115E90E6972b83e5a": 0.003531479800416611, + "0xC0AAbA6E0dD2Ca4C2BE7Df446C121C3E6118bdD2": 0.002460465472369189, + "0x496A936f46dFaa912F128CABFA01BA6F56a520c6": 0.003828941172828698, + "0x90DAeA825E9D43043C05725a4196382B881b1a73": 0.001099951354446733, + "0xd9e352554D0e4269d9B158d1baFC7975fd4d402C": 0.001843137211087484, + "0x79c8039C0cfBDC3cdF8d66eFB1AD2836E698ea3c": 0.002578484951824701, + "0xe1810961A12B5B38468fFc32aF3b5F8dA1EFdB53": 0.001783927430639374, + "0xF3579d18e82E8A1353D58D1B5a7265F4f5844A9c": 0.005735749368089457, + "0xBA93f72e240d7F45DB22EbF126c2D87dDE238918": 0.002541461042721758, + "0x9a4773EeEE73e34e1EE0E9A64E4b7453b0b04246": 0.00355486573687172, + "0x8Cf75F1D6974DB5215d81FBec287Ea8EEF35C95b": 0.002031467328715358, + "0x8578ffA6a6E9908B454CD38B93D3F11Ca8723A9A": 0.00303325222357865, + "0x06Ce05Db7D0A4539B3eC2fa6b81DFe11a32120eA": 0.003164680541865497, + "0x8BE6B927c4F3aa56D9c0DCf1be363b0081Fe0BD4": 0.002270355163329501, + "0x00dd323d8f4bDcEa52EDBdE935C1ee97C009c5a7": 0.002478951291953739, + "0xf8C9a3f1E55b9a91E413A8C8bB9F5f84C6d246cB": 0.003023094476691789, + "0x7b56128FAB23816D4a7520Ef691e2607af97B01c": 0.002055699820435307, + "0xD05F0F552d72947b471a4C4BEE98F9207E889482": 0.00170910539497277, + "0x80040d9c574156125E096d85AF6B6c86668d6CDF": 0.004290243713460643, + "0x7A75B62e21C490fe9a27A50a083D6a2b04c7fbbf": 0.003423006108420677, + "0x27459423cc0f816D965A97dCB90fa45774a18C3A": 0.003066765200276719, + "0x533758cC4EDF0568E51e322367A9Ec6fbE24E9E7": 0.004746336283500802, + "0xD02524BEeFd5164Eb28C77CD3eb2C7De887B891C": 0.004549383536034815, + "0x7FafB471bad0589FaBa53769DD8d76c5d79aB720": 0.003405642915183107, + "0xA3625b1dCB1e99dCC1B9BEB6ceD0965FAF4e20e5": 0.002327764794234669, + "0xd706bf4bb1560a73790D91B8fd585Cb5508db6ea": 0.004458846284913399, + "0x0724CFd1B40f56B506136D5A89EedDda31deA725": 0.002084534187021498, + "0x1379D42CC081790d6205712b79f6E133d798af81": 0.003699548183950676, + "0x3bcD8de636cEa72178D8f1285f5Af0dd02d0B142": 0.004366564988209448, + "0xe619ea101759B9D0c5dDC36b59f1F5e55FEB76B9": 0.003295701034330254, + "0x75F5607Fe0A27c57CCd7B1eD244Eee9499D68302": 0.002277257486379917, + "0xe57fe5bbDc76E8Af1448550cA56e7E36c8Fc8272": 0.002104225372548929, + "0xaA8eacF97AF9Bf3eB4cBB76E975a5D6aaA220606": 0.001864231000280281, + "0x60e0D8fef5d86615067dD713cA3ecCB2dC669993": 0.00259254404611745, + "0x239a01C50406Cd2d5943B408b49b32226741E1CB": 0.004448949574716135, + "0x00C3C106D11322c7aafECBF248cEE710ae3f0a5B": 0.002473782171469335, + "0x65DFdAec30d18F98791153A92F1f4cbf64839Da5": 0.002120777178210538, + "0x46Dd430cD21e39ef9A06b40406BEeF25B3810210": 0.002546090584532424, + "0x73714FE3e21C09FaE810380c15C64b5628E5d904": 0.002485605498299128, + "0x00Dd84F50e5699aA9F1a9f4f52c428BB305189be": 0.003304852110567445, + "0xF339487b61b99465BF3969f7AabC8e83D80D3d74": 0.000060540030398151, + "0xF94D1cfd380bbAa0d7Ca33E00700e7E6be836Ab1": 0.000493574581235319, + "0x0E054B1F4b103A1C92866B3205EcF818334caCf0": 0.000908470734297678, + "0x122Bc7CFfcdA5C1C7C5BE7Cd0E5943827Ca08AEE": 0.000348535850631998, + "0x08610322dfDa1dd2D129b647e13840e832D485e7": 0.000793309535678942, + "0x63d4E757AE3aa82751094BeF2Ce37dB0b303959E": 0.000706551392796436, + "0x609247305c7FD22515158ab5dD270997fb8EC766": 0.000407095546712405, + "0x92772bb3C161c573717865e59De038821935376C": 0.000013753666155892, + "0x9c0bCC942E775cdff33c64906561A3d75d9D0B79": 0.000486574057871009, + "0x81f981f743Ef69EECD5EA860A252f46825022Ac0": 0.000223951611787668, + "0xa2E5Dbd496e25A194a11FC3e4Ad5AdA199e827F4": 0.000429146132814596, + "0x7E1B249e6BAA2F60A87B14b43B1Ad731542bD9fF": 0.000944338902223686, + "0xD593f878270b61e64fa65dAA06728D0bA89C792A": 0.000328745764992469, + "0x48c7e0db3DAd3FE4Eb0513b86fe5C38ebB4E0F91": 0.000517900966894647, + "0x285D90Db77B246DbcA38cf0FbFCc3c0813202Cc9": 0.000045750842213171, + "0x90942873BEC9aA28a4957c1FF1C41fb3B8cf6a74": 0.000243392392826063, + "0xbFd42c1C4275Fc9663A6BB6b22246e138DF513Fc": 0.000086908331291376, + "0x634A6D52d63C18f6d20210B809cBE7f3192b0EBC": 0.000145224519364632, + "0xE7488e7f5c60bfa81D38965c02B4cC5AA6249A11": 0.001193660597737952, + "0xb2a275B464EdcF73c70EfdA20a5Ba5f742470D4e": 0.000302385576624338, + "0x4e61A9975D48f1518DF3e2fAdb4545E97ef4dCE2": 0.000014830561386827, + "0x8B6e491405eF885d4f070720F49f1383F1e6bc1D": 0.00017225303027436, + "0x670aC9fE190AB0Ac2D6829eE414F221794B22cDB": 0.000152267121603873, + "0x5D547923774921d7938349C1582239d19d5cCC4B": 0.000011915606361159, + "0xB01caEa8c6C47bbf4F4b4c5080Ca642043359C2E": 0.000080095678857014 + } +} \ No newline at end of file diff --git a/packages/affiliates/gas-rebate/voterGasRebateV2Utils.ts b/packages/affiliates/gas-rebate/voterGasRebateV2Utils.ts index 65ae86c2d1..73b871291f 100644 --- a/packages/affiliates/gas-rebate/voterGasRebateV2Utils.ts +++ b/packages/affiliates/gas-rebate/voterGasRebateV2Utils.ts @@ -265,8 +265,8 @@ export interface CorrectionPayoutJson { fromBlock: number; toBlock: number; countVoters: number; - totalRebateAmount: number; - shareholderPayout: { [address: string]: number }; + totalRebateAmount: string; + shareholderPayout: { [address: string]: string }; } export interface CorrectionAuditReport { @@ -1499,8 +1499,8 @@ function buildCorrectionPayoutJson( const sortedAddresses = Object.keys(consolidatedPayoutWei).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()) ); - const shareholderPayout = sortedAddresses.reduce((payout: { [address: string]: number }, address) => { - payout[address] = parseFloat(formatWeiToEthDecimalString(consolidatedPayoutWei[address])); + const shareholderPayout = sortedAddresses.reduce((payout: { [address: string]: string }, address) => { + payout[address] = formatWeiToEthDecimalString(consolidatedPayoutWei[address]); return payout; }, {}); const totalRebateWei = totalWei(consolidatedPayoutWei); @@ -1514,7 +1514,7 @@ function buildCorrectionPayoutJson( fromBlock, toBlock, countVoters: sortedAddresses.length, - totalRebateAmount: parseFloat(formatWeiToEthDecimalString(totalRebateWei)), + totalRebateAmount: formatWeiToEthDecimalString(totalRebateWei), shareholderPayout, }; } diff --git a/packages/affiliates/test/mocha-local/gas-rebate/VoterGasRebateV2Utils.js b/packages/affiliates/test/mocha-local/gas-rebate/VoterGasRebateV2Utils.js index d6ce979a15..4ce9b288e1 100644 --- a/packages/affiliates/test/mocha-local/gas-rebate/VoterGasRebateV2Utils.js +++ b/packages/affiliates/test/mocha-local/gas-rebate/VoterGasRebateV2Utils.js @@ -2,7 +2,6 @@ require("ts-node/register/transpile-only"); const { assert } = require("chai"); const { BigNumber, utils } = require("ethers"); -const { createHash } = require("crypto"); const fs = require("fs"); const os = require("os"); const path = require("path"); @@ -625,7 +624,7 @@ describe("VoterGasRebateV2 utils", function () { [correctionPositiveVoter]: BigNumber.from("1500000000000000000"), [correctionZeroVoter]: BigNumber.from("2000000000000000000"), [correctionNegativeVoter]: BigNumber.from("1000000000000000000"), - [correctionNewVoter]: BigNumber.from("250000000000000000"), + [correctionNewVoter]: BigNumber.from("250000000000000001"), }; const written = await runVotingV2CorrectionAudit({ manifestPath, @@ -649,13 +648,13 @@ describe("VoterGasRebateV2 utils", function () { assert.isTrue(fs.existsSync(written.auditJsonPath)); assert.isTrue(fs.existsSync(written.auditMarkdownPath)); assert.equal(written.payout.countVoters, 2); - assert.equal(written.payout.totalRebateAmount, 0.75); + assert.equal(written.payout.totalRebateAmount, "0.750000000000000001"); assert.deepEqual(written.payout.shareholderPayout, { - [correctionPositiveVoter]: 0.5, - [correctionNewVoter]: 0.25, + [correctionPositiveVoter]: "0.5", + [correctionNewVoter]: "0.250000000000000001", }); assert.notProperty(written.payout.shareholderPayout, correctionNegativeVoter); - assert.equal(written.report.consolidatedTopUp.totalWei, "750000000000000000"); + assert.equal(written.report.consolidatedTopUp.totalWei, "750000000000000001"); assert.equal(written.report.auditedRebates[0].deltas.positive.length, 2); assert.equal(written.report.auditedRebates[0].deltas.zero.length, 1); assert.equal(written.report.auditedRebates[0].deltas.negative.length, 1); @@ -798,58 +797,6 @@ describe("VoterGasRebateV2 utils", function () { ); }); - it("loads the committed Phase 6 Rebate 65-66 correction manifest with per-rebate policy parameters", function () { - const affiliatesDir = path.resolve(__dirname, "../../.."); - const manifestPath = path.join(affiliatesDir, "gas-rebate/corrections/Rebates_65_66_Correction_Manifest.json"); - const manifest = loadCorrectionManifest(manifestPath, { - baseDir: affiliatesDir, - expectedVotingContractAddress: votingAddress, - }); - - assert.equal(manifest.name, "March and February 2026 Rebate 65-66 VotingV2 correction audit"); - assert.equal(manifest.outputPrefix, "Correction_Rebates_65_66"); - assert.lengthOf(manifest.audits, 2); - assert.deepEqual( - manifest.audits.map((audit) => ({ - rebateFile: audit.rebateFile, - rebateNumber: audit.rebateNumber, - fromBlock: audit.fromBlock, - toBlock: audit.toBlock, - minStakedTokens: audit.minStakedTokens, - maxPriorityFeeGwei: audit.maxPriorityFeeGwei, - maxBlockLookBack: audit.maxBlockLookBack, - transactionConcurrency: audit.transactionConcurrency, - })), - [ - { - rebateFile: "gas-rebate/rebates/Rebate_66.json", - rebateNumber: 66, - fromBlock: 24558868, - toBlock: 24781026, - minStakedTokens: "1000", - maxPriorityFeeGwei: "0.001", - maxBlockLookBack: 250, - transactionConcurrency: 100, - }, - { - rebateFile: "gas-rebate/rebates/Rebate_65.json", - rebateNumber: 65, - fromBlock: 24358293, - toBlock: 24558867, - minStakedTokens: "1000", - maxPriorityFeeGwei: "0.001", - maxBlockLookBack: 250, - transactionConcurrency: 100, - }, - ] - ); - assert.include(manifest.audits[1].notes, "backward audit stop point"); - assert.deepEqual( - manifest.expectedDeltas.map((delta) => delta.rebateNumber), - [66, 66] - ); - }); - it("keeps committed Rebate 66 correction artifacts reviewable without committed audit JSON", function () { const affiliatesDir = path.resolve(__dirname, "../../.."); const outputDir = path.join(affiliatesDir, "gas-rebate/corrections"); @@ -866,18 +813,19 @@ describe("VoterGasRebateV2 utils", function () { assert.equal(payout.fromBlock, 24558868); assert.equal(payout.toBlock, 24781026); assert.equal(payout.countVoters, 585); + assert.equal(payout.totalRebateAmount, "1.095766860809837881"); assert.equal(Object.keys(payout.shareholderPayout).length, payout.countVoters); for (const expected of [ { address: utils.getAddress("0xf20737e48160a87dc9d1b26d8b63c796d2f1ea91"), deltaWei: "7088051537280779", - deltaEth: 0.007088051537280779, + deltaEth: "0.007088051537280779", }, { address: utils.getAddress("0x2a9437de0ccd4fd7b7d98831213acedefc7a1092"), deltaWei: "1902006430166225", - deltaEth: 0.001902006430166225, + deltaEth: "0.001902006430166225", }, ]) { assert.equal(payout.shareholderPayout[expected.address], expected.deltaEth); @@ -893,36 +841,6 @@ describe("VoterGasRebateV2 utils", function () { assert.include(markdown, "- Event validation passed: true"); }); - it("keeps committed Phase 6 Rebate 65-66 correction artifacts reviewable without committed audit JSON", function () { - const affiliatesDir = path.resolve(__dirname, "../../.."); - const outputDir = path.join(affiliatesDir, "gas-rebate/corrections"); - const manifestPath = path.join(outputDir, "Rebates_65_66_Correction_Manifest.json"); - const paths = getCorrectionArtifactPaths(outputDir, "Correction_Rebates_65_66"); - - assert.isTrue(fs.existsSync(paths.payoutPath)); - assert.isTrue(fs.existsSync(paths.auditMarkdownPath)); - - const payout = JSON.parse(fs.readFileSync(paths.payoutPath, "utf8")); - const markdown = fs.readFileSync(paths.auditMarkdownPath, "utf8"); - const manifestHash = createHash("sha256").update(fs.readFileSync(manifestPath)).digest("hex"); - - assert.equal(payout.votingContractAddress, votingAddress); - assert.equal(payout.rebate, 65); - assert.equal(payout.fromBlock, 24358293); - assert.equal(payout.toBlock, 24781026); - assert.equal(payout.countVoters, 591); - assert.equal(Object.keys(payout.shareholderPayout).length, payout.countVoters); - assert.include(markdown, "# VotingV2 Gas Rebate Correction Audit - March and February 2026"); - assert.include(markdown, `Manifest SHA-256: \`${manifestHash}\``); - assert.include(markdown, "### Rebate 66"); - assert.include(markdown, "### Rebate 65"); - assert.include(markdown, "- Notes: February 2026 backward audit stop point"); - assert.include(markdown, "- Positive delta total: 58 wei (0.000000000000000058 ETH)"); - assert.include(markdown, "- Negative delta total: -52 wei (-0.000000000000000052 ETH)"); - assert.include(markdown, "- Split count: 0"); - assert.include(markdown, "- Total: 1095766860809837939 wei (1.095766860809837939 ETH)"); - }); - it("documents the Phase 7 runbook and review checklist without concrete RPC URLs", function () { const affiliatesDir = path.resolve(__dirname, "../../.."); const readme = fs.readFileSync(path.join(affiliatesDir, "gas-rebate/README.md"), "utf8"); @@ -930,7 +848,7 @@ describe("VoterGasRebateV2 utils", function () { for (const requiredText of [ "Safe Chunk Size and Validation", "`MAX_BLOCK_LOOK_BACK=250` is the safe default chunk size", - "CUSTOM_NODE_URL=\"\"", + 'CUSTOM_NODE_URL=""', "March 2026 Rebate 66 Rerun", "Correction/audit mode is VotingV2-only", "Historical `Rebate_*.json` files are immutable", From c271cf7925dae78982bed02a3360200f4bf84c12 Mon Sep 17 00:00:00 2001 From: Pablo Maldonado Date: Thu, 30 Apr 2026 13:57:25 +0000 Subject: [PATCH 5/5] docs(gas-rebate): fix rebate 66 reproduction commands --- packages/affiliates/gas-rebate/README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/affiliates/gas-rebate/README.md b/packages/affiliates/gas-rebate/README.md index 1ddf0a96e4..0eee277f79 100644 --- a/packages/affiliates/gas-rebate/README.md +++ b/packages/affiliates/gas-rebate/README.md @@ -63,11 +63,17 @@ Do not raise `MAX_BLOCK_LOOK_BACK` for production payouts unless the audit repor ### March 2026 Rebate 66 Rerun -The March 2026 recompute uses the original paid Rebate 66 block range and policy parameters. Replace only the placeholder RPC URL: +The March 2026 recompute uses the original paid Rebate 66 block range and policy parameters. Because the paid +`Rebate_66.json` artifact is committed, temporarily remove it for this reproduction run so the monthly script sees +Rebate 65 as the latest paid rebate and writes `Rebate_66.json`. Replace only the placeholder RPC URL: ```bash cd packages/affiliates +REBATE_66_BACKUP_DIR="$(mktemp -d)" +cp gas-rebate/rebates/Rebate_66.json "$REBATE_66_BACKUP_DIR/Rebate_66.json" +rm gas-rebate/rebates/Rebate_66.json + CUSTOM_NODE_URL="" \ NODE_OPTIONS="--max-old-space-size=24000" \ OVERRIDE_FROM_BLOCK=24558868 \ @@ -77,6 +83,8 @@ TRANSACTION_CONCURRENCY=100 \ MAX_BLOCK_LOOK_BACK=250 \ MAX_PRIORITY_FEE_GWEI=0.001 \ yarn hardhat run ./gas-rebate/VoterGasRebateV2.ts --network mainnet + +diff -u "$REBATE_66_BACKUP_DIR/Rebate_66.json" gas-rebate/rebates/Rebate_66.json ``` ### Output Format @@ -202,11 +210,16 @@ cd packages/affiliates CUSTOM_NODE_URL="" \ NODE_OPTIONS="--max-old-space-size=24000" \ +OUTPUT_DIR="$(mktemp -d)" \ AUDIT_MANIFEST=gas-rebate/corrections/Rebate_66_Correction_Manifest.json \ yarn hardhat run ./gas-rebate/AuditVoterGasRebateV2.ts --network mainnet ``` -The script writes `Correction_Rebate_66.json`, `Correction_Rebate_66.audit.json`, and `Correction_Rebate_66.audit.md` under `gas-rebate/corrections/` unless `OUTPUT_DIR` changes the destination. Correction payout ETH amounts are emitted as decimal strings so they round-trip to exact wei. The `.audit.json` file is intentionally git-ignored because it can contain large transaction-level evidence; commit the correction payout JSON and `.audit.md` reviewer summary. +The command above writes `Correction_Rebate_66.json`, `Correction_Rebate_66.audit.json`, and +`Correction_Rebate_66.audit.md` to a fresh temporary directory so it does not overwrite committed correction artifacts. +Without `OUTPUT_DIR`, the script writes under `gas-rebate/corrections/`. Correction payout ETH amounts are emitted as +decimal strings so they round-trip to exact wei. The `.audit.json` file is intentionally git-ignored because it can +contain large transaction-level evidence; commit the correction payout JSON and `.audit.md` reviewer summary. ### Overpayments