proposal-33-compensate-rela.../scripts/calculateLosses.ts

68 lines
2.7 KiB
TypeScript

import * as dotenv from "dotenv";
import { Web3 } from "web3";
import fs from "fs";
import path from "path";
import axios from "axios";
import { RelayerLosses, TxReceipt } from "./types";
dotenv.config();
const web3 = new Web3(process.env.MAINNET_RPC_URL);
const routerAddress = "0xd90e2f925DA726b50C4Ed8D0Fb90Ad053324F31b";
async function fetchFailedWithdrawals() {
const attackStartBlock = 18363087;
const attackEndBlock = 18366622;
let failedWithdrawalTransactions = [];
for (let blockNumber = attackStartBlock; blockNumber <= attackEndBlock; blockNumber++) {
let block = null;
while (block == null)
try {
block = await web3.eth.getBlock(blockNumber);
} catch (e) {}
const results = await Promise.allSettled(block.transactions.map((tx) => web3.eth.getTransactionReceipt(tx as string)));
const transactions = results.filter((r) => r.status === "fulfilled").map((r) => (r as PromiseFulfilledResult<TxReceipt>).value);
failedWithdrawalTransactions.push(...transactions.filter((tx) => tx.to === routerAddress.toLowerCase() && tx.status == 0));
}
return failedWithdrawalTransactions;
}
async function calculateLosses(failedTransactions: Array<TxReceipt>): Promise<RelayerLosses> {
return failedTransactions.reduce((acc, tx) => {
const gasExpenses = BigInt(tx.gasUsed) * BigInt(tx.effectiveGasPrice!);
acc[tx.from] = acc[tx.from] ? acc[tx.from] + gasExpenses : gasExpenses;
return acc;
}, {} as RelayerLosses);
}
async function getEthRateInTorn(): Promise<bigint> {
const api = "https://api.binance.com/api/v3/ticker/price?symbol=";
const fetchPrice = async (symbol: string) => Number((await axios.get(api + symbol)).data.price);
const tornInUsd = await fetchPrice("TORNBUSD");
const ethInUsd = await fetchPrice("ETHUSDT");
return BigInt(Math.floor(ethInUsd / tornInUsd));
}
function writeData(relayerLossesInTorn: RelayerLosses) {
const data = Object.entries(relayerLossesInTorn)
.map(([relayer, amount]) => `${web3.utils.toChecksumAddress(relayer)} = ${amount.toString()} // ~ ${amount / 10n ** 18n} TORN`)
.join("\n");
fs.writeFileSync(path.join(".", "data", "relayerLosses.txt"), data);
}
async function main() {
const failedWithdrawals = await fetchFailedWithdrawals();
const relayerLosses = await calculateLosses(failedWithdrawals);
console.log(relayerLosses);
const ethRateInTorn = await getEthRateInTorn();
const relayerLossesInTorn = Object.fromEntries(
Object.entries(relayerLosses).map(([relayer, amounthInEth]) => [relayer, amounthInEth * ethRateInTorn])
);
writeData(relayerLossesInTorn);
console.log("All data about relayer losses written successfully.");
}
main();