From d8127e9b4a7341c8da887e5c750c95f8cf9f829a Mon Sep 17 00:00:00 2001 From: Mikhailo Shabodyash Date: Thu, 21 Nov 2024 17:23:14 +0200 Subject: [PATCH] feat: workflow and script for multiplier --- ...te-multiplier-for-rewards-v2-campaign.yaml | 65 +++++++++++++++++++ scripts/rewards_v2/utils.ts | 28 ++++++++ tasks/deployment_manager/task.ts | 32 ++++++++- 3 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/calculate-multiplier-for-rewards-v2-campaign.yaml diff --git a/.github/workflows/calculate-multiplier-for-rewards-v2-campaign.yaml b/.github/workflows/calculate-multiplier-for-rewards-v2-campaign.yaml new file mode 100644 index 000000000..2e5beec8a --- /dev/null +++ b/.github/workflows/calculate-multiplier-for-rewards-v2-campaign.yaml @@ -0,0 +1,65 @@ +name: Calculate multiplier for RewardsV2 Campaign +on: + workflow_dispatch: + inputs: + network: + type: choice + description: Network + options: + - fuji + - mainnet + - goerli + - sepolia + - mumbai + - polygon + - arbitrum + - arbitrum-goerli + - base + - base-goerli + - linea-goerli + - optimism + - scroll-goerli + - scroll + required: true + deployment: + description: Deployment Name (e.g. "usdc", "weth") + required: true + duration: + description: Duration in seconds + required: true + amount: + description: Amount in tokens (e.g. 1, 100, 1000) + required: true +jobs: + calculate-multiplier-for-rewards-v2-campaign: + name: Calculate multiplier for RewardsV2 Campaign + runs-on: ubuntu-latest + env: + ETHERSCAN_KEY: ${{ secrets.ETHERSCAN_KEY }} + SNOWTRACE_KEY: ${{ secrets.SNOWTRACE_KEY }} + INFURA_KEY: ${{ secrets.INFURA_KEY }} + QUICKNODE_KEY: ${{ secrets.QUICKNODE_KEY }} + POLYGONSCAN_KEY: ${{ secrets.POLYGONSCAN_KEY }} + ARBISCAN_KEY: ${{ secrets.ARBISCAN_KEY }} + BASESCAN_KEY: ${{ secrets.BASESCAN_KEY }} + LINEASCAN_KEY: ${{ secrets.LINEASCAN_KEY }} + OPTIMISMSCAN_KEY: ${{ secrets.OPTIMISMSCAN_KEY }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '16' + + - name: Install packages + run: yarn install --non-interactive --frozen-lockfile + + - name: Compile + run: yarn hardhat compile + + - name: Check types + run: yarn tsc + + - name: Run Calculate Multiplier for RewardsV2 Campaign + run: yarn hardhat calculateMultiplier --network ${{ github.event.inputs.network }} --deployment ${{ github.event.inputs.deployment }} --duration ${{ github.event.inputs.duration }} --amount ${{ github.event.inputs.amount }} diff --git a/scripts/rewards_v2/utils.ts b/scripts/rewards_v2/utils.ts index b2c5a5026..155bf699f 100644 --- a/scripts/rewards_v2/utils.ts +++ b/scripts/rewards_v2/utils.ts @@ -19,6 +19,7 @@ import { getEtherscanUrl } from '../../plugins/import/etherscan'; import { multicallAddresses } from './constants'; import { CampaignType } from './types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { ethers } from 'ethers'; interface FileData { timestamp: number; @@ -422,3 +423,30 @@ export const getAllTransferEvents = async (comet: CometInterface, startBlock: nu return allEvents; }; + +export const calculateMultiplier = async (totalSpeed: bigint, duration: number, amount: bigint) => { + // to distribute exactly the amount of rewards in the given duration + // we need to adjust the speed with the multiplier + + // amount = totalSpeed * multiplier * duration + // multiplier = amount / (totalSpeed * duration) + const multiplier = BigNumber.from(amount * BigInt(1e15) * BigInt(1e18)).div((totalSpeed * BigInt(duration))); + + console.log(`\n=========================================`); + console.log(`Amount to of tokens distribute: ${amount}`); + console.log(`Duration in seconds: ${duration}`); + console.log(`=========================================`); + + console.log(`\n=========================================`); + console.log(`Total speed per day: ${ethers.utils.formatUnits(totalSpeed * BigInt(86400), 15)}`); + console.log(`Basic rewards for given duration: ${ethers.utils.formatUnits(totalSpeed * BigInt(duration), 15)}`); + console.log(`Formula for multiplier: amount / (totalSpeed * duration)`); + console.log(`=========================================`); + + console.log(`\n=========================================`); + console.log(`Multiplier %: ${ethers.utils.formatUnits(multiplier.mul(100), 18).toString()}`); + console.log(`Multiplier with decimals: ${multiplier.toString()}`); + console.log(`=========================================\n`); + + return multiplier; +}; diff --git a/tasks/deployment_manager/task.ts b/tasks/deployment_manager/task.ts index 340947fd9..24f8084e5 100644 --- a/tasks/deployment_manager/task.ts +++ b/tasks/deployment_manager/task.ts @@ -5,7 +5,7 @@ import { HardhatRuntimeEnvironment, HardhatConfig } from 'hardhat/types'; import { DeploymentManager, VerifyArgs } from '../../plugins/deployment_manager'; import { impersonateAddress } from '../../plugins/scenario/utils'; import hreForBase from '../../plugins/scenario/utils/hreForBase'; -import { generateMerkleTreeForCampaign } from '../../scripts/rewards_v2/utils'; +import { generateMerkleTreeForCampaign, calculateMultiplier } from '../../scripts/rewards_v2/utils'; // TODO: Don't depend on scenario's hreForBase function getForkEnv(env: HardhatRuntimeEnvironment, deployment: string): HardhatRuntimeEnvironment { @@ -372,3 +372,33 @@ task('generateMerkleTree', 'Generates a Merkle Tree for a given campaign') console.error('Error during Merkle tree generation:', error); } }); + +task('calculateMultiplier', 'Calculates the multiplier for a rewardsV2 campaign') + .addParam('deployment', 'The deployment to use (e.g., usdc, weth)') + .addParam('duration', 'The duration of the campaign in seconds') + .addParam('amount', 'The amount of rewards to distribute in tokens, not wei, e.g., 10, 50, 100') + .setAction(async ({ deployment, duration, amount }, env) => { + const network = env.network.name; + const dm = new DeploymentManager( + network, + deployment, + getForkEnv(env, deployment) + ); + + const comet = await dm.contract('comet'); + if (!comet) { + throw new Error('Comet contract not found'); + } + const supplySpeed = await comet.baseTrackingSupplySpeed(); + const borrowSpeed = await comet.baseTrackingBorrowSpeed(); + + const totalSpeed = supplySpeed.add(borrowSpeed).toBigInt(); + + calculateMultiplier( + totalSpeed, + +duration, + BigInt(amount) + ); + + console.log('Finished!'); + });