Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/testnet-rewards/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Testnet rewards

Every quarter, testnet (tethys) workers are paid in real SQD on Arbitrum One through a fresh [`MerkleDistributor`](../contracts/src/MerkleDistributor.sol). The budget is 25 workers × $225 at the quarter's SQD/USD price, split pro rata by each owner's testnet rewards.
Every quarter, testnet (tethys) workers are paid in real SQD on Arbitrum One through a fresh [`MerkleDistributor`](../contracts/src/MerkleDistributor.sol). The budget is $75 per worker per month for a target of 25 workers, i.e. $1,875 a month or $225 × 25 a quarter, at the quarter's SQD/USD price. It is split pro rata by each owner's testnet rewards across however many workers run, so with more than 25 workers each gets less than $75. With fewer than 25 rewarded workers, the budget shrinks to $225 per rewarded worker.

[`testnet-rewards.ts`](./testnet-rewards.ts) does the data side. You deploy and fund the contract yourself with the commands it prints; the script never sends a transaction. The record of every payout is in [subsquid/cdn](https://github.com/subsquid/cdn) under `src/points/`. Nothing is committed here.

Expand Down
19 changes: 15 additions & 4 deletions packages/testnet-rewards/testnet-rewards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ async function fetchSquidRewards(
from: Date,
to: Date,
allowIncomplete: boolean,
): Promise<{ rows: [string, bigint][]; incomplete: { indexedUpTo: string | null } | null }> {
): Promise<{ rows: [string, bigint][]; workers: number; incomplete: { indexedUpTo: string | null } | null }> {
const url = process.env.TESTNET_SQUID_PG_URL;
if (!url) {
fail(
Expand Down Expand Up @@ -246,7 +246,11 @@ async function fetchSquidRewards(
if (!/^\d+$/.test(row.total)) fail(`non-integer reward total "${row.total}" for ${row.wallet}`);
return [normalizeAddress(row.wallet, "squid real_owner_id"), BigInt(row.total)];
});
return { rows: result, incomplete };
const [count] = await sql`
select count(distinct worker_id)::int as workers from worker_reward
where timestamp >= ${from.toISOString()}::timestamptz and timestamp < ${to.toISOString()}::timestamptz
`;
return { rows: result, workers: count.workers, incomplete };
} finally {
await sql.close();
}
Expand Down Expand Up @@ -391,7 +395,7 @@ async function build(argv: string[]) {

console.log(`Period: ${formatDay(from)} to ${formatDay(addDays(to, -1))} inclusive (timestamp >= ${from.toISOString()} and < ${to.toISOString()})`);

const workers = values.workers ?? DEFAULT_WORKERS;
let workers = values.workers ?? DEFAULT_WORKERS;
const targetUsd = values["target-usd"] ?? DEFAULT_TARGET_USD;
let price: string | null = values.price ?? null;
let priceSource: string | null = values.price ? "--price" : null;
Expand All @@ -416,7 +420,14 @@ async function build(argv: string[]) {
} else {
source = "squid:subsquid-network-testnet";
if (to.getTime() > Date.now() && !values["allow-incomplete"]) fail(`the period has not ended yet (last day ${formatDay(addDays(to, -1))})`);
({ rows: raw, incomplete } = await fetchSquidRewards(from, to, values["allow-incomplete"]!));
let rewarded: number;
({ rows: raw, workers: rewarded, incomplete } = await fetchSquidRewards(from, to, values["allow-incomplete"]!));
console.log(`Workers rewarded in the window: ${rewarded}`);
// The budget is $targetUsd for each of up to `workers` workers: with fewer workers, nobody gets more than that.
if (rewarded < Number(workers)) {
warn(`only ${rewarded} workers were rewarded, fewer than ${workers}; sizing the budget for ${rewarded}`);
workers = String(rewarded);
}
}

if (raw) {
Expand Down
Loading