Skip to content

Commit

Permalink
Merge pull request #353 from lidofinance/feature/si-1434-fix-rewards-fee
Browse files Browse the repository at this point in the history
fix: fee from staking router
  • Loading branch information
Vorobeyko authored Jun 18, 2024
2 parents 5786131 + dcc0a44 commit 94abff0
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 18 deletions.
125 changes: 125 additions & 0 deletions abi/partialStakingRouter.abi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
[
{
"inputs": [
{
"internalType": "address",
"name": "_depositContract",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "stakingModuleId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "stakingModuleFee",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "treasuryFee",
"type": "uint256"
},
{
"indexed": false,
"internalType": "address",
"name": "setBy",
"type": "address"
}
],
"name": "StakingModuleFeesSet",
"type": "event"
},
{
"inputs": [],
"name": "FEE_PRECISION_POINTS",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "TOTAL_BASIS_POINTS",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getLido",
"outputs": [{ "internalType": "address", "name": "", "type": "address" }],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getStakingFeeAggregateDistribution",
"outputs": [
{ "internalType": "uint96", "name": "modulesFee", "type": "uint96" },
{ "internalType": "uint96", "name": "treasuryFee", "type": "uint96" },
{ "internalType": "uint256", "name": "basePrecision", "type": "uint256" }
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getStakingFeeAggregateDistributionE4Precision",
"outputs": [
{ "internalType": "uint16", "name": "modulesFee", "type": "uint16" },
{ "internalType": "uint16", "name": "treasuryFee", "type": "uint16" }
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getStakingRewardsDistribution",
"outputs": [
{
"internalType": "address[]",
"name": "recipients",
"type": "address[]"
},
{
"internalType": "uint256[]",
"name": "stakingModuleIds",
"type": "uint256[]"
},
{
"internalType": "uint96[]",
"name": "stakingModuleFees",
"type": "uint96[]"
},
{ "internalType": "uint96", "name": "totalFee", "type": "uint96" },
{
"internalType": "uint256",
"name": "precisionPoints",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getTotalFeeE4Precision",
"outputs": [
{ "internalType": "uint16", "name": "totalFee", "type": "uint16" }
],
"stateMutability": "view",
"type": "function"
},
{ "stateMutability": "payable", "type": "receive" }
]
23 changes: 23 additions & 0 deletions consts/staking-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { CHAINS } from '@lido-sdk/constants';
import { contractHooksFactory } from '@lido-sdk/react';
import invariant from 'tiny-invariant';

import { PartialStakingRouterAbi__factory } from 'generated/factories/PartialStakingRouterAbi__factory';

export const STAKING_ROUTER_BY_NETWORK: {
[key in CHAINS]?: string;
} = {
[CHAINS.Mainnet]: '0xFdDf38947aFB03C621C71b06C9C70bce73f12999',
[CHAINS.Holesky]: '0xd6EbF043D30A7fe46D1Db32BA90a0A51207FE229',
};

export const getStakingRouterAddress = (chainId: CHAINS): string => {
const address = STAKING_ROUTER_BY_NETWORK[chainId];
invariant(address, 'chain is not supported');
return address;
};

export const stakingRouter = contractHooksFactory(
PartialStakingRouterAbi__factory,
(chainId) => getStakingRouterAddress(chainId),
);
13 changes: 5 additions & 8 deletions features/stake/stake-faq/list/lido-fee.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import { FC } from 'react';
import { Accordion } from '@lidofinance/lido-ui';
import { useContractSWR, useSTETHContractRPC } from '@lido-sdk/react';

import { DATA_UNAVAILABLE } from 'consts/text';
import { useProtocolFee } from 'shared/hooks/use-protocol-fee';

export const LidoFee: FC = () => {
const contractRpc = useSTETHContractRPC();
const lidoFee = useContractSWR({
contract: contractRpc,
method: 'getFee',
});
const protocolFee = useProtocolFee();

const feeValue =
lidoFee.initialLoading || !lidoFee.data
protocolFee.initialLoading || !protocolFee.data
? DATA_UNAVAILABLE
: `${lidoFee.data / 100}%`;
: `${protocolFee.data}%`;

return (
<Accordion summary="What fee is applied by Lido? What is this used for?">
Expand Down
15 changes: 5 additions & 10 deletions features/stake/stake-form/stake-form-info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,20 @@ import { useWatch } from 'react-hook-form';

import { Zero } from '@ethersproject/constants';
import { DataTable, DataTableRow } from '@lidofinance/lido-ui';
import { useContractSWR, useSTETHContractRPC } from '@lido-sdk/react';

import { DATA_UNAVAILABLE } from 'consts/text';
import { STRATEGY_CONSTANT } from 'consts/swr-strategies';
import { FormatPrice, FormatToken } from 'shared/formatters';
import { useEthUsd } from 'shared/hooks/use-eth-usd';
import { useProtocolFee } from 'shared/hooks/use-protocol-fee';

import { StakeFormInput, useStakeFormData } from './stake-form-context';

export const StakeFormInfo = () => {
const { gasCost, loading } = useStakeFormData();
const amount = useWatch<StakeFormInput, 'amount'>({ name: 'amount' });
const contractRpc = useSTETHContractRPC();
const lidoFee = useContractSWR({
contract: contractRpc,
method: 'getFee',
config: STRATEGY_CONSTANT,
});

const { usdAmount, initialLoading: isEthUsdLoading } = useEthUsd(gasCost);
const protocolFee = useProtocolFee();

return (
<DataTable data-testid="stakeFormInfo">
Expand All @@ -40,11 +35,11 @@ export const StakeFormInfo = () => {
<DataTableRow
title="Reward fee"
data-testid="lidoFee"
loading={lidoFee.initialLoading}
loading={protocolFee.initialLoading}
help="Please note: this fee applies to staking rewards only,
and is NOT taken from your staked amount."
>
{!lidoFee.data ? DATA_UNAVAILABLE : `${lidoFee.data / 100}%`}
{!protocolFee.data ? DATA_UNAVAILABLE : `${protocolFee.data}%`}
</DataTableRow>
</DataTable>
);
Expand Down
46 changes: 46 additions & 0 deletions shared/hooks/use-protocol-fee.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { formatEther } from '@ethersproject/units';

import { CHAINS } from '@lido-sdk/constants';
import { useLidoSWR, useSDK } from '@lido-sdk/react';
import { useStakingRouter } from './use-stakign-router-contract';
import { PartialStakingRouterAbi } from 'generated/PartialStakingRouterAbi';

import { config } from 'config';
import { STRATEGY_CONSTANT } from 'consts/swr-strategies';

export const useProtocolFee = () => {
const { chainId } = useSDK();
const { contractRpc } = useStakingRouter();

return useLidoSWR<number>(
['swr:useProtocolFee', chainId, contractRpc, config.enableQaHelpers],
// @ts-expect-error broken lidoSWR typings
async (
_key: string,
_chainId: CHAINS,
contractRpc: PartialStakingRouterAbi,
shouldMock: boolean,
) => {
const mockDataString = window.localStorage.getItem('protocolFee');

if (shouldMock && mockDataString) {
try {
const mockData = JSON.parse(mockDataString);
return mockData;
} catch (e) {
console.warn('Failed to load mock data');
console.warn(e);
}
}

const fee = await contractRpc.getStakingFeeAggregateDistribution();
const value = Number(formatEther(fee.modulesFee.add(fee.treasuryFee)));

return value.toFixed(0);
},
{
...STRATEGY_CONSTANT,
refreshInterval: 60000,
},
);
};
7 changes: 7 additions & 0 deletions shared/hooks/use-stakign-router-contract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { stakingRouter } from 'consts/staking-router';

export const useStakingRouter = () => {
const contractRpc = stakingRouter.useContractRPC();

return { contractRpc };
};

0 comments on commit 94abff0

Please sign in to comment.