diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_1.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_1.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_1.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_1.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_2.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_2.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_2.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_2.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_3.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_3.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_3.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_3.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_4.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_4.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Dark_4.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Dark_4.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_1.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_1.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_1.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_1.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_2.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_2.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_2.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_2.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_3.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_3.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_3.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_3.png diff --git a/apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_4.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_4.png similarity index 100% rename from apps/developer-hub/public/images/ois/OIS_Rewards_Example_Light_4.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/OIS_Rewards_Example_Light_4.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_investigation_dark.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_investigation_dark.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_investigation_dark.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_investigation_dark.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_investigation_light.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_investigation_light.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_investigation_light.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_investigation_light.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_pool_post_dark.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_post_dark.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_pool_post_dark.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_post_dark.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_pool_post_light.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_post_light.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_pool_post_light.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_post_light.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_pool_pre_dark.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_pre_dark.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_pool_pre_dark.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_pre_dark.png diff --git a/apps/developer-hub/public/images/ois/ois_slashing_pool_pre_light.png b/apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_pre_light.png similarity index 100% rename from apps/developer-hub/public/images/ois/ois_slashing_pool_pre_light.png rename to apps/developer-hub/content/docs/oracle-integrity-staking/images/ois_slashing_pool_pre_light.png diff --git a/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx b/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx index c95c535013..fd9ce27931 100644 --- a/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx +++ b/apps/developer-hub/content/docs/oracle-integrity-staking/reward-examples.mdx @@ -5,6 +5,14 @@ description: >- --- import DualModeImage from "../../../src/components/DualModeImage"; +import OISExample1Dark from "./images/OIS_Rewards_Example_Dark_1.png"; +import OISExample1Light from "./images/OIS_Rewards_Example_Light_1.png"; +import OISExample2Dark from "./images/OIS_Rewards_Example_Dark_2.png"; +import OISExample2Light from "./images/OIS_Rewards_Example_Light_2.png"; +import OISExample3Dark from "./images/OIS_Rewards_Example_Dark_3.png"; +import OISExample3Light from "./images/OIS_Rewards_Example_Light_3.png"; +import OISExample4Dark from "./images/OIS_Rewards_Example_Dark_4.png"; +import OISExample4Light from "./images/OIS_Rewards_Example_Light_4.png"; NOTE: All the symbols used in the examples are explained in the [Mathematical Representation](./mathematical-representation) section. @@ -14,8 +22,8 @@ This example takes the case of one pool where the pool has stake from only the p
@@ -42,8 +50,8 @@ This example takes the case where the pool has stake from both the publisher and
@@ -70,8 +78,8 @@ This example takes the case where the combined stake of both the publisher and t
@@ -98,8 +106,8 @@ This example demonstrates how the delegation fee affect the reward distribution
@@ -203,3 +211,11 @@ C_{p_{option2}} &= 100 + 100 \cdot \sum_{s \in \text{\{$s_{6}$,.., $s_{10}$\}}} &= 100 + 50 = 150 \end{aligned} $$ + +## Reward Calculator + +Use the calculator below to calculate publisher and delegator rewards based on your inputs. + +import RewardSimulator from "../../../src/components/RewardSimulator"; + + diff --git a/apps/developer-hub/content/docs/oracle-integrity-staking/slashing-rulebook.mdx b/apps/developer-hub/content/docs/oracle-integrity-staking/slashing-rulebook.mdx index 55f1381743..a205031907 100644 --- a/apps/developer-hub/content/docs/oracle-integrity-staking/slashing-rulebook.mdx +++ b/apps/developer-hub/content/docs/oracle-integrity-staking/slashing-rulebook.mdx @@ -6,6 +6,12 @@ description: >- --- import DualModeImage from "../../../src/components/DualModeImage"; +import OISSlashingInvestigationDark from "./images/ois_slashing_investigation_dark.png"; +import OISSlashingInvestigationLight from "./images/ois_slashing_investigation_light.png"; +import OISSlashingPoolPreDark from "./images/ois_slashing_pool_pre_dark.png"; +import OISSlashingPoolPreLight from "./images/ois_slashing_pool_pre_light.png"; +import OISSlashingPoolPostDark from "./images/ois_slashing_pool_post_dark.png"; +import OISSlashingPoolPostLight from "./images/ois_slashing_pool_post_light.png"; # Purpose and Scope @@ -111,8 +117,8 @@ It was found that 7 of the 9 publishers were influencing the price of `FOO/USD` The other 2 publishers were found publish price closely to the mediuan of the reference data. @@ -122,8 +128,8 @@ The other 2 publishers were found publish price closely to the mediuan of the re - From the investigation, \$200K of preventable liquidations were identified from on chain data, the Pythian Council could adjust the amount of stake slashed to 500K PYTH or 100bps (assuming PYTH/USD = $0.40). @@ -134,8 +140,8 @@ The other 2 publishers were found publish price closely to the mediuan of the re - Delegators to `pool_1` would see their stake slashed by 100bps of 4M PYTH, ie. 40K PYTH, resulting in **3.96M** residual delegated stake. diff --git a/apps/developer-hub/src/components/RewardSimulator/index.module.scss b/apps/developer-hub/src/components/RewardSimulator/index.module.scss new file mode 100644 index 0000000000..458d458171 --- /dev/null +++ b/apps/developer-hub/src/components/RewardSimulator/index.module.scss @@ -0,0 +1,86 @@ +@use "@pythnetwork/component-library/theme"; + +.card { + margin-top: theme.spacing(6); +} + +.inputGrid { + display: grid; + grid-template-columns: 1fr; + gap: theme.spacing(6); + padding: theme.spacing(4); + + @include theme.breakpoint("sm") { + grid-template-columns: 1fr 1fr; + } +} + +.inputGroup { + display: flex; + flex-direction: column; + gap: theme.spacing(2); +} + +.input { + padding: theme.spacing(2) theme.spacing(3); + border: 1px solid theme.color("border"); + border-radius: theme.border-radius("lg"); + background-color: theme.color("background", "primary"); + color: theme.color("foreground"); + transition: all 0.15s ease-in-out; + + &:focus { + outline: 2px solid theme.color("focus"); + outline-offset: -2px; + border-color: transparent; + } +} + +.resultsSection { + border-top: 1px solid theme.color("border"); + margin-top: theme.spacing(6); + padding: theme.spacing(6) theme.spacing(4) 0; +} + +.resultsGrid { + display: grid; + grid-template-columns: 1fr; + gap: theme.spacing(6); + + @include theme.breakpoint("sm") { + grid-template-columns: 1fr 1fr; + } +} + +.resultGroup { + display: flex; + flex-direction: column; + gap: theme.spacing(3); +} + +.resultTitle { + font-size: theme.font-size("lg"); + font-weight: theme.font-weight("semibold"); + color: theme.color("foreground"); +} + +.resultList { + display: flex; + flex-direction: column; + gap: theme.spacing(1); + margin: 0; +} + +.resultTerm { + font-size: theme.font-size("sm"); + color: theme.color("muted"); + font-weight: theme.font-weight("medium"); + margin: 0; +} + +.resultValue { + font-family: theme.font-family("monospace"); + font-size: theme.font-size("sm"); + margin: 0; + margin-bottom: theme.spacing(2); +} diff --git a/apps/developer-hub/src/components/RewardSimulator/index.tsx b/apps/developer-hub/src/components/RewardSimulator/index.tsx new file mode 100644 index 0000000000..c647533c72 --- /dev/null +++ b/apps/developer-hub/src/components/RewardSimulator/index.tsx @@ -0,0 +1,231 @@ +"use client"; + +import { Card } from "@pythnetwork/component-library/Card"; +import { Label } from "@pythnetwork/component-library/unstyled/Label"; +import { Input } from "@pythnetwork/component-library/unstyled/TextField"; +import { useState, useCallback } from "react"; + +import styles from "./index.module.scss"; + +// Components for mathematical notation +const MathExpression = ({ children }: { children: React.ReactNode }) => ( + {children} +); + +// Component for subscripts and superscripts +const Sub = ({ children }: { children: React.ReactNode }) => ( + {children} +); + +const Sup = ({ children }: { children: React.ReactNode }) => ( + {children} +); + +const RewardSimulator: React.FC = () => { + const [rewards, setRewards] = useState({ + // These are the initial values for the reward simulator based on default values + publisher: 26, + delegator: 24, + publisherRate: 13, + delegatorRate: 8, + }); + + const doSubmit = useCallback((e: React.FormEvent) => { + e.currentTarget.requestSubmit(); + }, []); + + const recalculateRewards = useCallback( + (e: React.FormEvent) => { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + + const publisherStake = Number(formData.get("publisherStake")) || 0; + const delegatorStake = Number(formData.get("delegatorStake")) || 0; + const maxCap = Number(formData.get("maxCap")) || 0; + const delegatorFee = Number(formData.get("delegatorFee")) || 0; + const rewardRate = Number(formData.get("rewardRate")) || 0; + + const totalStake = publisherStake + delegatorStake; + const eligibleAmount = Math.min(totalStake, maxCap); + const totalReward = (rewardRate / 100) * eligibleAmount; + + const publisherRewardBase = + (rewardRate / 100) * Math.min(publisherStake, maxCap); + const delegatorRewardBase = totalReward - publisherRewardBase; + + const delegatorFeeAmount = (delegatorFee / 100) * delegatorRewardBase; + + const finalDelegatorReward = delegatorRewardBase - delegatorFeeAmount; + const finalPublisherReward = publisherRewardBase + delegatorFeeAmount; + + setRewards({ + publisher: Number(finalPublisherReward.toFixed(2)), + delegator: Number(finalDelegatorReward.toFixed(2)), + publisherRate: Number( + ((finalPublisherReward * 100) / publisherStake).toFixed(2), + ), + delegatorRate: Number( + ((finalDelegatorReward * 100) / delegatorStake).toFixed(2), + ), + }); + }, + [], + ); + + return ( + +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+
+

Calculated Rewards

+
+
+ Publisher Reward ( + + Rp + p + + ): +
+
{rewards.publisher}
+
+ Delegator Reward ( + + Rd + p + + ): +
+
{rewards.delegator}
+
+
+ +
+

+ Calculated Reward Rates (Yearly) +

+
+
+ Publisher Rate ( + + rp + p + + ): +
+
{rewards.publisherRate}%
+
+ Delegator Rate ( + + rd + p + + ): +
+
{rewards.delegatorRate}%
+
+
+
+
+
+
+ ); +}; + +export default RewardSimulator; diff --git a/packages/component-library/src/theme.scss b/packages/component-library/src/theme.scss index ba1e93b1d5..0587c74df4 100644 --- a/packages/component-library/src/theme.scss +++ b/packages/component-library/src/theme.scss @@ -30,6 +30,21 @@ $font-weight: ( @return map-get-strict($font-weight, $weight); } +$font-family: ( + "monospace": ( + "ui-monospace", + "sfmono-regular", + "consolas", + "Liberation Mono", + "menlo", + "monospace", + ), +); + +@function font-family($family) { + @return map-get-strict($font-family, $family); +} + $font-size: ( "xxs": 0.6875rem, "xs": 0.75rem,