Skip to content

Commit

Permalink
Merge pull request #34 from tetu-io/dev-ruby
Browse files Browse the repository at this point in the history
Add distribute veTetu
  • Loading branch information
belbix authored Apr 9, 2024
2 parents a757b48 + 1e07434 commit ebb16f0
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 20 deletions.
63 changes: 63 additions & 0 deletions scripts/utils/tools/veTETU-utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
/* tslint:disable:no-string-literal */
import fetch from 'node-fetch';
import { ethers } from 'hardhat';
import { IVeTetu__factory } from '../../../typechain/factories/contracts/tools/VeTETUVotingPower.sol';
import { IERC721__factory } from '../../../typechain';
import { formatUnits } from 'ethers/lib/utils';
import { Misc } from './Misc';

const VE_TETU = '0x6FB29DD17fa6E27BD112Bc3A2D0b8dae597AeDA4'.toLowerCase();
const GRAPHQL_ENDPOINT = 'https://api.thegraph.com/subgraphs/name/tetu-io/tetu-v2'

// tslint:disable-next-line:no-var-requires
Expand Down Expand Up @@ -45,3 +51,60 @@ export async function getVeTetuHolders(top: number): Promise<any> {
`
);
}

export async function getTokenIdByBlock(block: number | string = 'latest'): Promise<number> {
const abi = [
'function tokenId() view returns (uint256)'
]
const contract = new ethers.Contract(VE_TETU, abi, ethers.provider);
return contract.tokenId({
blockTag: block
});
}

export async function collectUserBalance(tokenId: number, block: number | string = 'latest'): Promise<Record<string, string[]>> {
const balances: Record<string, string[]> = {};
const veTetu = IVeTetu__factory.connect(VE_TETU, ethers.provider);
const erc721 = IERC721__factory.connect(VE_TETU, ethers.provider);
for (let i = 0; i < tokenId; i++) {
console.log('Progress', i);
const balance = await veTetu.balanceOfNFT(i, {
blockTag: block,
});
const owner = (await erc721.ownerOf(i, {
blockTag: block,
})).toLowerCase();

if (balances[owner]) {
balances[owner].push(formatUnits(balance, 18));
} else {
balances[owner] = [];
balances[owner] = [formatUnits(balance, 18)];
}
}
return balances;
}

export function convertToRewardPercent(balances: Record<string, string[]>): Record<string, number> {
const rewards: Record<string, number> = {};
const rewardsInPercent: Record<string, number> = {};
let total = 0;
for (const [key, value] of Object.entries(balances)) {
if (Misc.ZERO_ADDRESS === key) {
continue;
}
const totalBalance = value.reduce((acc, cur) => acc + parseFloat(cur), 0);
if (totalBalance === 0) {
continue;
}
rewards[key] = totalBalance;
total += totalBalance;
}
console.log(rewards);
for (const [key, value] of Object.entries(rewards)) {
rewardsInPercent[key] = value / total * 100;
}
return rewardsInPercent;
}


64 changes: 44 additions & 20 deletions scripts/utils/xtetuBAL-airdrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {getPawnshopData, getSnapshotVoters} from "./tools/voting-utils";
import {expect} from "chai";
import {TransferEvent} from "../../typechain/contracts/third_party/IERC20Extended";
import {getAllUserByBlock} from './users/users-balances';
import { collectUserBalance, convertToRewardPercent, getTokenIdByBlock } from './tools/veTETU-utils';

// After airdrop receiving from all sources you need to liquidate all tokens to USDC
// USDC should be on the dedicated msig - send it to BRIBER address
Expand Down Expand Up @@ -262,7 +263,7 @@ async function main() {
throw new Error('not enough xtetuBal');
}

await distributeBribes(signer, veTetuPartOfTetu);
await distributeBribes(signer, veTetuPartOfTetu, BLOCK);

const usdcAllowance = await IERC20__factory.connect(MaticAddresses.USDC_TOKEN, signer).allowance(signer.address, distributor.address);
const xtetuBALAllowance = await IERC20__factory.connect(MaticAddresses.xtetuBAL_TOKEN, signer).allowance(signer.address, distributor.address);
Expand Down Expand Up @@ -344,26 +345,49 @@ async function main() {
async function distributeBribes(
signer: SignerWithAddress,
amount: number,
block: number
) {
throw new Error('TODO'); // todo
//
// console.log('--------- Start distribute veTETU bribes', amount);
//
// const balanceTETU = await IERC20__factory.connect(MaticAddresses.TETU_TOKEN, signer).balanceOf(signer.address);
//
// console.log('balanceTETU', +formatUnits(balanceTETU));
//
// if (amount <= +formatUnits(balanceTETU)) {
// console.log('transfer tetu');
// const tp = await DeployerUtilsLocal.txParams();
// await RunHelper.runAndWait(() => IERC20__factory.connect(MaticAddresses.TETU_TOKEN, signer).transfer(
// BRIBE_DISTRIBUTOR,
// parseUnits(amount.toFixed(18)),
// {...tp}
// ));
// } else {
// throw new Error('not enough tokens');
// }
console.log('--------- Start distribute veTETU bribes', amount);

const balanceTETU = await IERC20__factory.connect(MaticAddresses.TETU_TOKEN, signer).balanceOf(signer.address);
const distributor = XtetuBALDistributor__factory.connect(DISTRIBUTOR, signer);

console.log('balanceTETU', +formatUnits(balanceTETU));

if (amount <= +formatUnits(balanceTETU)) {
console.log('transfer tetu');
const tp = await DeployerUtilsLocal.txParams();
await RunHelper.runAndWait(() => IERC20__factory.connect(MaticAddresses.TETU_TOKEN, signer).transfer(
DISTRIBUTOR,
parseUnits(amount.toFixed(18)),
{...tp}
));
const tokenId = await getTokenIdByBlock(block);
console.log('tokenId', tokenId);
const balances = await collectUserBalance(tokenId, block);
const rewardPercents = convertToRewardPercent(balances);
console.log('rewardPercents', rewardPercents);
const usersForVeTetu: string[] = [];
const usersForVeTetuAmount: number[] = [];
for (const [key, value] of Object.entries(rewardPercents)) {
const reward = value * amount / 100;
usersForVeTetu.push(key);
usersForVeTetuAmount.push(reward);
console.log(`User ${key} will receive ${reward} TETU ${value}% of total amount`)
}
await RunHelper.runAndWait(() => distributor.distribute(
[
usersForVeTetu
],
[
usersForVeTetuAmount
],
parseUnits(amount.toFixed(18)),
{...tp}
));
} else {
throw new Error('not enough tokens');
}
}

main()
Expand Down

0 comments on commit ebb16f0

Please sign in to comment.