2023-06-03 20:53:36 +03:00
|
|
|
import Web3 from "web3";
|
|
|
|
import BigNumber from "bignumber.js"
|
|
|
|
import { AbiItem } from 'web3-utils';
|
|
|
|
import { EthAddress, IStaker } from "./@types/staker";
|
|
|
|
|
|
|
|
import * as dotenv from "dotenv";
|
|
|
|
import { governanceAddress, governanceRewardsProposalBlock, hackBlock, oldStakingAddress } from "./config";
|
|
|
|
|
|
|
|
import GovernanceAbi from "../abi/GovernanceAbi.json";
|
|
|
|
import StakingAbi from "../abi/StakingABI.json";
|
|
|
|
|
|
|
|
dotenv.config();
|
|
|
|
|
|
|
|
const web3 = new Web3(process.env.MAINNET_RPC_URL as string);
|
|
|
|
|
|
|
|
function getGovernanceFunctionSelector(functionName: string): string {
|
|
|
|
const lockFunctionAbi = GovernanceAbi.find(item => item.name == functionName);
|
|
|
|
if (!lockFunctionAbi) throw new Error(`Cannot find function ${functionName} in Governance contract ABI`);
|
|
|
|
|
|
|
|
const selector = web3.eth.abi.encodeFunctionSignature(lockFunctionAbi as AbiItem);
|
|
|
|
|
|
|
|
return selector;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function getAddressesStakersWithProssibleRewards(): Promise<Array<EthAddress>> {
|
|
|
|
const governanceContract = new web3.eth.Contract(GovernanceAbi as AbiItem[], governanceAddress);
|
2023-06-12 16:22:32 +03:00
|
|
|
|
|
|
|
/* Don't need to fetch all "lock" or "lockAndApproval" transactions from Governance contract,
|
|
|
|
* because user rewards start updating only when RewardUpdateSuccessful events is emitted.
|
|
|
|
*/
|
2023-06-03 20:53:36 +03:00
|
|
|
const rewardsUpdateEvents =
|
|
|
|
await governanceContract.getPastEvents("RewardUpdateSuccessful", { fromBlock: governanceRewardsProposalBlock });
|
|
|
|
|
|
|
|
const governanceStakers = rewardsUpdateEvents.map(event => event.returnValues.account as string);
|
|
|
|
|
|
|
|
return [...new Set(governanceStakers)];
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function getStakersWithRewardsBeforeHack(): Promise<Array<IStaker>> {
|
|
|
|
const stakingContract = new web3.eth.Contract(StakingAbi as AbiItem[], oldStakingAddress);
|
|
|
|
const stakersAddresses = await getAddressesStakersWithProssibleRewards();
|
|
|
|
|
|
|
|
let stakersWithRewardsBeforeHack: Array<IStaker> = [];
|
|
|
|
for (const address of stakersAddresses) {
|
2023-06-12 16:22:32 +03:00
|
|
|
// Check stakers rewards on previous block before hack
|
2023-06-03 20:53:36 +03:00
|
|
|
const rewardsBeforeHack = await stakingContract.methods.checkReward(address).call({}, hackBlock - 1);
|
2023-06-12 16:22:32 +03:00
|
|
|
// Discard stakers with rewards less than 1 TORN, because accruing each reward requires paying gas
|
2023-06-03 20:53:36 +03:00
|
|
|
if (BigNumber(rewardsBeforeHack).div(1e18).isGreaterThan(1))
|
|
|
|
stakersWithRewardsBeforeHack.push({ address, rewardBalance: BigNumber(rewardsBeforeHack) });
|
|
|
|
}
|
|
|
|
|
|
|
|
return stakersWithRewardsBeforeHack;
|
|
|
|
}
|