Skip to content

Commit

Permalink
Incentives v2 dyn (#1237)
Browse files Browse the repository at this point in the history
* Calculation fix for rewards in uni v2

* fix: reward calc fix done

* feat: core v2 calc dynamic

* refactor: moved to helpers

* Changes done with the new code for Push Staking Pool

* feat: format fix

* feat: covev2 cal

---------

Co-authored-by: abhishek-01k <[email protected]>
  • Loading branch information
MdTeach and abhishek-01k authored Aug 18, 2023
1 parent b0f8748 commit ce7894f
Show file tree
Hide file tree
Showing 19 changed files with 5,232 additions and 238 deletions.
21 changes: 11 additions & 10 deletions src/components/yield/YieldPushFeeV3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const YieldPushFeeV3 = ({
}

setTxInProgressWithdraw(true);
const unstakeAmount = formatTokens(userDataPush?.userstakedAmount?.stakedAmount);
const unstakeAmount = formatTokens(userDataPush?.userStaked);

if (unstakeAmount == 0) {
setUnstakeErrorMessage("Nothing to unstake, You need to stake first");
Expand Down Expand Up @@ -159,7 +159,7 @@ const YieldPushFeeV3 = ({
}

setTxInProgressClaimRewards(true);
const withdrawAmount = userDataPush?.totalClaimableReward;
const withdrawAmount = userDataPush?.availableRewards;

if (withdrawAmount == 0) {
setWithdrawErrorMessage("No Rewards to Claim")
Expand Down Expand Up @@ -271,6 +271,8 @@ const YieldPushFeeV3 = ({
const stakingModalToast = useToast();
const isMobile = useDeviceWidthCheck(600);

console.log("User Data Push",userDataPush);

return (
<Container>
<StakingComponent
Expand Down Expand Up @@ -381,7 +383,7 @@ const YieldPushFeeV3 = ({
<>
<EpochNo>Current Epoch</EpochNo>
<EpochNo>
{PUSHPoolstats?.currentEpoch.toNumber()}
{PUSHPoolstats?.currentEpochNumber}
</EpochNo>
</>
) : (
Expand Down Expand Up @@ -409,7 +411,7 @@ const YieldPushFeeV3 = ({
</StakingToolTip>
</InfoSpan>
</DataTitle>
<DataValue> {numberWithCommas(formatTokens(userDataPush?.userstakedAmount.stakedAmount))} PUSH</DataValue>
<DataValue> {numberWithCommas(formatTokens(userDataPush?.userStaked))} PUSH</DataValue>
</ItemHV2>
<ItemHV2 justifyContent="space-between" margin={isMobile ? "0px 0px 12px 0px" : "0px 13px 12px 13px"}>
<DataTitle>
Expand All @@ -424,7 +426,7 @@ const YieldPushFeeV3 = ({
</InfoSpan>

</DataTitle>
<DataValue> {numberWithCommas(formatTokens(userDataPush?.claimedReward))} PUSH</DataValue>
<DataValue> {numberWithCommas((userDataPush?.claimedReward).toFixed(2))} PUSH</DataValue>
</ItemHV2>
<ItemHV2 justifyContent="space-between" margin={isMobile ? "0px 0px 12px 0px" : "0px 13px 12px 13px"}>
<DataTitle>
Expand All @@ -437,9 +439,8 @@ const YieldPushFeeV3 = ({
<ImageV2 src={InfoLogo} alt="Info-Logo" width="16px" style={{ cursor: 'pointer' }} />
</StakingToolTip>
</InfoSpan>

</DataTitle>
<DataValue> {numberWithCommas((userDataPush?.potentialUserReward).toFixed(2))} PUSH</DataValue>
<DataValue> {numberWithCommas((userDataPush?.potentialReward).toFixed(2))} PUSH</DataValue>
</ItemHV2>
<ItemHV2 justifyContent="space-between" margin={isMobile ? "0px 0px 12px 0px" : "0px 13px 12px 13px"}>
<DataTitle>
Expand All @@ -454,7 +455,7 @@ const YieldPushFeeV3 = ({
</InfoSpan>

</DataTitle>
<DataValue> {numberWithCommas(userDataPush?.totalClaimableReward)} PUSH</DataValue>
<DataValue> {numberWithCommas((userDataPush?.availableRewards).toFixed(2))} PUSH</DataValue>
</ItemHV2>
</ItemVV2>
) : (
Expand Down Expand Up @@ -497,7 +498,7 @@ const YieldPushFeeV3 = ({
</ItemHV2>
<ButtonsContainer>

{formatTokens(userDataPush?.userstakedAmount.stakedAmount) === "0" || unstakeErrorMessage !== null ?
{formatTokens(userDataPush?.userStaked) === 0 || unstakeErrorMessage !== null ?
<StakingToolTip
error={true}
ToolTipTitle={unstakeErrorMessage ? unstakeErrorMessage : "Nothing to unstake, Stake First"}
Expand Down Expand Up @@ -536,7 +537,7 @@ const YieldPushFeeV3 = ({

}

{userDataPush?.totalClaimableReward === "0.00" ?
{userDataPush?.availableRewards === 0.00 ?
<StakingToolTip
bottom={'-30px'}
ToolTipTitle={"No Rewards to Claim"}
Expand Down
4 changes: 3 additions & 1 deletion src/components/yield/YieldUniswapV3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ const YieldUniswapV3 = ({
return;
}

if (!lpPoolStats.currentEpochPUSH || lpPoolStats.currentEpochPUSH == 1) {
console.log("Lp POOL stats", lpPoolStats)

if (!lpPoolStats.currentEpochLP || lpPoolStats.currentEpochLP == 1) {
uniswapV2Toast.showMessageToast({
toastTitle: 'Error',
toastMessage: `Harvest unlocks from Epoch 2!)`,
Expand Down
6 changes: 4 additions & 2 deletions src/config/config-dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ export const addresses = {
depYieldFarmLP:"0xc2886D0e7DAd16cc92b1156Dc9A0b0D3F047FD15",

//For Yield Farm V2
stakingV2: "0x6C83ce5eE433d53E10b64E277B1cf5207C37b662",
yieldFarmLP: "0x13ac63901c8fD5797939099553582951fAbAFDE3",
// stakingV2: "0x6C83ce5eE433d53E10b64E277B1cf5207C37b662",
stakingV2: "0x0B318CA01Cec62bB29526591f368b44f4b8a0303",
yieldFarmLP: "0x576c46b328433AaDcb9d9cDd81E0A92852bb0B6F",
// yieldFarmLP: "0x13ac63901c8fD5797939099553582951fAbAFDE3",
pushCoreV2: "0x23346b732d56d34ec4e890419fbfb8548216a799",
uniV2LPToken: "0x698839247E5b83572fFF6ccdcf386CC37e60bEf5",
pushToken: "0x2b9bE9259a4F5Ba6344c1b1c07911539642a2D33",
Expand Down
4 changes: 1 addition & 3 deletions src/helpers/StakingHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { ethers } from "ethers";


export const formatTokens = (tokens) => {
if (tokens) {
return tokens.div(ethers.BigNumber.from(10).pow(18)).toString();
}
return tokens.div(ethers.BigNumber.from(10).pow(18)).toString();
};

export const numberWithCommas = (x) => {
Expand Down
1 change: 1 addition & 0 deletions src/helpers/pushStaking/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src'
254 changes: 254 additions & 0 deletions src/helpers/pushStaking/src/CoreV2Reward.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
import { ethers } from "ethers";
import { PushCoreV2 } from "../types";
import { Helpers } from "./helpers";
import { StateType } from "./types";

export class CoreV2Reward {
public STATE: StateType;

public coreV2Contract: PushCoreV2;
public userAddress: string;

constructor(coreV2Contract: PushCoreV2, userAddress: string) {
this.coreV2Contract = coreV2Contract;
this.userAddress = userAddress;
this.STATE = Helpers.getEmptyState();
}

public async initState() {
// setup the block infos
const coreV2Contract = this.coreV2Contract;

const currentBlockNumber = await coreV2Contract.provider.getBlockNumber();
const genesisEpoch = await coreV2Contract
.genesisEpoch()
.then((res) => res.toNumber());

const currentEpoch = Helpers.lastEpochRelative(
genesisEpoch,
currentBlockNumber
);

this.STATE.currentBlockNumber = currentBlockNumber;
this.STATE.genesisEpoch = genesisEpoch;
this.STATE.currentEpoch = currentEpoch;
this.STATE.currentBlockNumber = currentBlockNumber;
this.STATE.genesisEpoch = genesisEpoch;
this.STATE.currentEpoch = currentEpoch;

const epochs = Array.from({ length: currentEpoch + 1 }, (_, i) => i);
const epochRewards = await Promise.all(
epochs.map((ep) => coreV2Contract.epochRewards(ep))
);
const epochToTotalStakedWeight = await Promise.all(
epochs.map((ep) => coreV2Contract.epochToTotalStakedWeight(ep))
);
const lastEpochInitializedBlock = await coreV2Contract.provider
.getStorageAt(coreV2Contract.address, 129)
.then((hexStr) => Number(hexStr));
const lastTotalStakeEpochInitialized = await coreV2Contract.provider
.getStorageAt(coreV2Contract.address, 130)
.then((hexStr) => Number(hexStr));

this.STATE.lastEpochInitialized = lastEpochInitializedBlock;
this.STATE.lastTotalStakeEpochInitialized = lastTotalStakeEpochInitialized;
this.STATE.epochRewards = epochRewards;
this.STATE.epochToTotalStakedWeight = epochToTotalStakedWeight;

this.STATE.previouslySetEpochRewards =
await coreV2Contract.previouslySetEpochRewards();

// set user info
const userFeeInfo = await coreV2Contract.userFeesInfo(this.userAddress);
this.STATE.userFeesInfo.stakedAmount = userFeeInfo.stakedAmount;
this.STATE.userFeesInfo.stakedWeight = userFeeInfo.stakedWeight;
this.STATE.userFeesInfo.lastStakedBlock = userFeeInfo.lastStakedBlock;
this.STATE.userFeesInfo.lastClaimedBlock = userFeeInfo.lastClaimedBlock;
this.STATE.userFeesInfo.epochToUserStakedWeight = await Promise.all(
epochs.map((ep) =>
Helpers.epochToUserStakedWeight(
coreV2Contract.provider as ethers.providers.JsonRpcProvider,
this.userAddress,
ep,
this.coreV2Contract.address
)
)
);
}

private async _setupEpochsRewardAndWeights(_userWeight: number) {
const coreV2Contract = this.coreV2Contract;
const genesisEpoch = await coreV2Contract
.genesisEpoch()
.then((res) => res.toNumber());

const _lastEpochInitiliazed = Helpers.lastEpochRelative(
genesisEpoch,
this.STATE.lastEpochInitialized
);

const _currentEpoch = this.STATE.currentEpoch;

// Setting up Epoch Based Rewards
console.log(
"\n\nDoing with: _currentEpoch, _lastEpochInitiliazed",
_currentEpoch,
_lastEpochInitiliazed,
"\n"
);

if (_currentEpoch > _lastEpochInitiliazed || _currentEpoch == 1) {
const PROTOCOL_POOL_FEES = await coreV2Contract.PROTOCOL_POOL_FEES();
const previouslySetEpochRewards =
await coreV2Contract.previouslySetEpochRewards();

const availableRewardsPerEpoch = PROTOCOL_POOL_FEES.sub(
previouslySetEpochRewards
);

const _epochGap = _currentEpoch - _lastEpochInitiliazed;

if (_epochGap > 1) {
this.STATE.epochRewards[_currentEpoch - 1] = this.STATE.epochRewards[
_currentEpoch - 1
].add(availableRewardsPerEpoch);
} else {
this.STATE.epochRewards[_currentEpoch] = Helpers.toBN(
this.STATE.epochRewards[_currentEpoch].toString()
).add(availableRewardsPerEpoch);
}

this.STATE.lastEpochInitialized =
await coreV2Contract.provider.getBlockNumber();
this.STATE.previouslySetEpochRewards = PROTOCOL_POOL_FEES;
}

// Setting up Epoch Based TotalWeight
if (
this.STATE.lastTotalStakeEpochInitialized == 0 ||
this.STATE.lastTotalStakeEpochInitialized == _currentEpoch
) {
this.STATE.epochToTotalStakedWeight[_currentEpoch] =
this.STATE.epochToTotalStakedWeight[_currentEpoch].add(_userWeight);
} else {
for (
let i = this.STATE.lastTotalStakeEpochInitialized + 1;
i <= _currentEpoch - 1;
i++
) {
if (this.STATE.epochToTotalStakedWeight[i].toNumber() == 0) {
this.STATE.epochToTotalStakedWeight[i] =
this.STATE.epochToTotalStakedWeight[
this.STATE.lastTotalStakeEpochInitialized
];
}
}

this.STATE.epochToTotalStakedWeight[_currentEpoch] =
this.STATE.epochToTotalStakedWeight[
this.STATE.lastTotalStakeEpochInitialized
].add(_userWeight);
}

this.STATE.lastTotalStakeEpochInitialized = _currentEpoch;
}

private async _adjustUserAndTotalStake(_userWeight: number) {
await this._setupEpochsRewardAndWeights(_userWeight);

const currentEpoch = this.STATE.currentEpoch;

const userStakedWeight = this.STATE.userFeesInfo.stakedWeight;

if (userStakedWeight.isZero()) {
this.STATE.userFeesInfo.stakedWeight = Helpers.toBN(_userWeight);
} else {
const lastStakedEpoch = Helpers.lastEpochRelative(
this.STATE.genesisEpoch,
this.STATE.userFeesInfo.lastStakedBlock.toNumber()
);

if (currentEpoch == lastStakedEpoch) {
this.STATE.userFeesInfo.stakedWeight =
userStakedWeight.add(_userWeight);
} else {
// Initiating 2.2 Case: User stakes again but in Different Epoch
for (let i = lastStakedEpoch; i <= currentEpoch; i++) {
if (i != currentEpoch) {
this.STATE.userFeesInfo.epochToUserStakedWeight[i] =
userStakedWeight;
} else {
this.STATE.userFeesInfo.stakedWeight =
userStakedWeight.add(_userWeight);

this.STATE.userFeesInfo.epochToUserStakedWeight[i] =
this.STATE.userFeesInfo.stakedWeight;
}
}
}
}

if (_userWeight != 0) {
this.STATE.userFeesInfo.lastStakedBlock = Helpers.toBN(
this.STATE.currentBlockNumber
);
}
}

private calculateEpochRewards(_epochId: number) {
return this.STATE.userFeesInfo.epochToUserStakedWeight[_epochId]
.mul(this.STATE.epochRewards[_epochId])
.div(this.STATE.epochToTotalStakedWeight[_epochId].add(1));
}

public async estimateHarvestAll() {
await this.initState();

const _tillEpoch = this.STATE.currentEpoch - 1;

await this._adjustUserAndTotalStake(0);

const currentEpoch = this.STATE.currentEpoch;

if (!(currentEpoch > _tillEpoch)) {
return Helpers.toBN(0);
}

const nextFromEpoch = Helpers.lastEpochRelative(
this.STATE.genesisEpoch,
Math.max(
this.STATE.userFeesInfo.lastClaimedBlock.toNumber(),
this.STATE.genesisEpoch
)
);

if (!(_tillEpoch >= nextFromEpoch)) {
return Helpers.toBN(0);
}

let rewards = Helpers.toBN(0);
for (let i = nextFromEpoch; i <= _tillEpoch; i++) {
const claimableReward = this.calculateEpochRewards(i);
rewards = rewards.add(claimableReward);
}

return rewards;
}

public async getUserPotentialEpochReward() {
await this.initState();
await this._setupEpochsRewardAndWeights(0);

const epochRewards = this.STATE.epochRewards[this.STATE.currentEpoch];
const totalStakedWeight =
this.STATE.epochToTotalStakedWeight[this.STATE.currentEpoch];
const userstakedWeight = this.STATE.userFeesInfo.stakedWeight;
const potentialReward = userstakedWeight
.mul(epochRewards)
.div(totalStakedWeight);
const currentEpochNumber = this.STATE.currentEpoch;

const userStaked = this.STATE.userFeesInfo.stakedAmount;
return { potentialReward, epochRewards, userStaked, currentEpochNumber };
}
}
10 changes: 10 additions & 0 deletions src/helpers/pushStaking/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const Constants = {
config: {
SLOTS: {
userFeesInfo: 134,
},
},

// epochDuration: 100,
epochDuration: 21 * 7156,
};
Loading

0 comments on commit ce7894f

Please sign in to comment.