-
Notifications
You must be signed in to change notification settings - Fork 35
OIS Docs #420
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
OIS Docs #420
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
a45ab0a
initial commit
aditya520 4ccbeae
(first example)
aditya520 9896683
fix
aditya520 5f069f9
Design principles and implementation of OIS
aditya520 1b6da69
added math
aditya520 48270d1
wip-added examples
aditya520 035583c
calculations
aditya520 5e8b8d2
changes
aditya520 b43df17
changes
aditya520 dd0632f
align
aditya520 16ba053
added publisher ranking
aditya520 486245f
publisher ranking done
aditya520 466e9d7
edits and fixes to examples
YaserJazouane dfafea8
minor fix
YaserJazouane 25fc245
minor formatting changes
YaserJazouane 6eb23c7
requested changes
aditya520 e24087c
tiny chnages
aditya520 4c21958
interactive sim
aditya520 196eea1
fix
aditya520 8118f50
pre-commit
aditya520 1bef4e1
initial commit of the slashing rulebook
YaserJazouane b8d9c3e
adding slashing rulebook
YaserJazouane 3accfbc
Moving slashing rulebook to OIS section
YaserJazouane 99f3547
updates to the rulebook
YaserJazouane 8e77510
formatting
YaserJazouane b65bd56
added example 6
aditya520 4a0993b
added example 6
aditya520 064ab69
fix formatting
YaserJazouane a70548d
minor fixes to symbology
YaserJazouane 6659f41
minor fixes to symbology
YaserJazouane fa0f0fd
minor fixes to symbology
YaserJazouane 5f40c42
fixing symbology
YaserJazouane 146f2df
Fix staking cap bar issues
cprussin c99b645
requested changes
aditya520 27172c8
requested changes
aditya520 9e96d69
Update pages/home/oracle-integrity-staking/examples.mdx
aditya520 2b96bbe
Update pages/home/oracle-integrity-staking/examples.mdx
aditya520 57831e0
Update pages/home/oracle-integrity-staking/examples.mdx
aditya520 81c9b1a
requested changes
aditya520 e28b451
minor changes
YaserJazouane 4036c32
Update pages/home/oracle-integrity-staking/mathematical-representatio…
aditya520 5535be9
requested changes
aditya520 06981c9
nits
aditya520 34908e8
minor change
YaserJazouane d4dd31d
minor changes
YaserJazouane File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import React, { useState, useEffect } from "react"; | ||
import "katex/dist/katex.min.css"; | ||
import Latex from "react-latex-next"; | ||
|
||
const RewardSimulator: React.FC = () => { | ||
const [publisherStake, setPublisherStake] = useState(200); | ||
const [delegatorStake, setDelegatorStake] = useState(300); | ||
const [maxCap, setMaxCap] = useState(500); | ||
const [delegatorFee, setDelegatorFee] = useState(2); | ||
const [rewardRate, setRewardRate] = useState(10); | ||
|
||
const [publisherReward, setPublisherReward] = useState(0); | ||
const [delegatorReward, setDelegatorReward] = useState(0); | ||
const [publisherRewardRate, setPublisherRewardRate] = useState(0); | ||
const [delegatorRewardRate, setDelegatorRewardRate] = useState(0); | ||
|
||
useEffect(() => { | ||
const calculateRewards = () => { | ||
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; | ||
|
||
setPublisherReward(Number(finalPublisherReward.toFixed(2))); | ||
setDelegatorReward(Number(finalDelegatorReward.toFixed(2))); | ||
setPublisherRewardRate( | ||
Number(((finalPublisherReward * 100) / publisherStake).toFixed(2)) | ||
); | ||
setDelegatorRewardRate( | ||
Number(((finalDelegatorReward * 100) / delegatorStake).toFixed(2)) | ||
); | ||
}; | ||
|
||
calculateRewards(); | ||
}, [publisherStake, delegatorStake, maxCap, delegatorFee, rewardRate]); | ||
|
||
return ( | ||
<div className="border border-gray-300 dark:border-gray-700 p-6 rounded-lg"> | ||
<h3 className="text-lg font-semibold mb-4">Reward Simulator</h3> | ||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4"> | ||
<div> | ||
<label className="block mb-2"> | ||
<Latex>{"Publisher Stake ($S_p^p$):"}</Latex> | ||
</label> | ||
<input | ||
type="number" | ||
value={publisherStake} | ||
onChange={(e) => setPublisherStake(Number(e.target.value))} | ||
className="w-full p-2 border rounded bg-transparent" | ||
/> | ||
</div> | ||
<div> | ||
<label className="block mb-2"> | ||
<Latex>{"Delegator Stake ($S_p^d$):"}</Latex> | ||
</label> | ||
<input | ||
type="number" | ||
value={delegatorStake} | ||
onChange={(e) => setDelegatorStake(Number(e.target.value))} | ||
className="w-full p-2 border rounded bg-transparent" | ||
/> | ||
</div> | ||
<div> | ||
<label className="block mb-2"> | ||
<Latex>{"Maximum Cap ($C_p$):"}</Latex> | ||
</label> | ||
<input | ||
type="number" | ||
value={maxCap} | ||
onChange={(e) => setMaxCap(Number(e.target.value))} | ||
className="w-full p-2 border rounded bg-transparent" | ||
/> | ||
</div> | ||
<div> | ||
<label className="block mb-2"> | ||
<Latex>{"Delegator Fee ($f$) (%):"}</Latex> | ||
</label> | ||
<input | ||
type="number" | ||
value={delegatorFee} | ||
onChange={(e) => setDelegatorFee(Number(e.target.value))} | ||
className="w-full p-2 border rounded bg-transparent" | ||
/> | ||
</div> | ||
<div> | ||
<label className="block mb-2"> | ||
<Latex>{"Reward Rate ($r$) (%):"}</Latex> | ||
</label> | ||
<input | ||
type="number" | ||
value={rewardRate} | ||
onChange={(e) => setRewardRate(Number(e.target.value))} | ||
className="w-full p-2 border rounded bg-transparent" | ||
/> | ||
</div> | ||
</div> | ||
<div className="flex mt-6"> | ||
<div className="flex-1"> | ||
<h4 className="font-semibold mb-2">Calculated Rewards:</h4> | ||
<p> | ||
<Latex>{`Publisher Reward ($R^p_p$): ${publisherReward}`}</Latex> | ||
</p> | ||
<p> | ||
<Latex>{`Delegator Reward ($R^d_p$): ${delegatorReward}`}</Latex> | ||
</p> | ||
</div> | ||
<div className="flex-1 ml-6"> | ||
<h4 className="font-semibold mb-2">Calculated Reward Rates:</h4> | ||
<p> | ||
<Latex>{`Publisher Reward Rate ($r^p_p$): ${publisherRewardRate}%`}</Latex> | ||
</p> | ||
<p> | ||
<Latex>{`Delegator Reward Rate ($r^d_p$): ${delegatorRewardRate}%`}</Latex> | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default RewardSimulator; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import React, { type ReactNode, useMemo } from "react"; | ||
|
||
interface StakingCapBarProps { | ||
totalLength?: number; | ||
height?: number; | ||
fillPercentage: number; | ||
secondFillPercentage: number; | ||
firstFillLabel?: string; | ||
secondFillLabel?: string; | ||
totalLabel?: string; | ||
} | ||
|
||
export default function StakingCapBar({ | ||
totalLength = 500, | ||
height = 80, | ||
fillPercentage, | ||
secondFillPercentage, | ||
firstFillLabel, | ||
secondFillLabel, | ||
totalLabel, | ||
}: StakingCapBarProps) { | ||
const clampedFillPercentage = useMemo( | ||
() => Math.min(100, Math.max(0, fillPercentage)), | ||
[fillPercentage] | ||
); | ||
const clampedSecondFillPercentage = useMemo( | ||
() => | ||
Math.min(100 - clampedFillPercentage, Math.max(0, secondFillPercentage)), | ||
[clampedFillPercentage, secondFillPercentage] | ||
); | ||
const totalFillPercentage = useMemo( | ||
() => clampedFillPercentage + clampedSecondFillPercentage, | ||
[clampedFillPercentage, clampedSecondFillPercentage] | ||
); | ||
|
||
return ( | ||
<div | ||
className="rounded-lg relative border border-4 border-[#7142CF] p-1 bg-white whitespace-nowrap" | ||
style={{ | ||
width: `${totalLength}px`, | ||
height: `${height}px`, | ||
}} | ||
role="progressbar" | ||
aria-valuenow={totalFillPercentage} | ||
aria-valuemin={0} | ||
aria-valuemax={100} | ||
> | ||
<Bar color="#5c48e4" fillPercent={clampedFillPercentage}> | ||
{firstFillLabel} | ||
</Bar> | ||
<Bar color="#f0b6bb" fillPercent={clampedSecondFillPercentage}> | ||
{secondFillLabel} | ||
</Bar> | ||
<div className="absolute right-0 bottom-full mb-[1.65rem]"> | ||
{totalLabel && <Label>{totalLabel}</Label>} | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
type BarProps = { | ||
fillPercent: number; | ||
children?: ReactNode | undefined; | ||
color: string; | ||
}; | ||
|
||
const Bar = ({ fillPercent, children, color }: BarProps) => ( | ||
<div | ||
className="inline-block h-full transition-all duration-300 ease-in-out relative" | ||
style={{ | ||
backgroundColor: color, | ||
width: `${fillPercent}%`, | ||
}} | ||
> | ||
{children && <Label>{children}</Label>} | ||
</div> | ||
); | ||
|
||
const Label = ({ children }: { children: ReactNode }) => ( | ||
<div | ||
className="absolute top-full left-full transform -translate-x-1/2 mt-2 text-xs font-medium text-gray-800 dark:text-gray-200 whitespace-nowrap" | ||
style={{ | ||
transition: "left 300ms ease-in-out", | ||
}} | ||
> | ||
{children} | ||
</div> | ||
); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Oracle Integrity Staking (OIS) | ||
|
||
This document outlines the design principles and implementation details of the [Oracle Integrity Staking (OIS)](https://staking.pyth.network/) protocol. | ||
|
||
## Design Principles | ||
|
||
OIS's economic design focuses on awarding and penalizing stakers over the primary dimension of data accuracy. | ||
|
||
Stakers are incentivized to help maintain data quality by receiving rewards from an open-ended pool. However, they also face the risk of having their stake slashed as a penalty for failing to maintain data accuracy. | ||
|
||
The core design principles behind OIS include the following: | ||
|
||
- Oracle Integrity Staking secures all current and future price feeds produced by the Pyth Network. | ||
- Data Publishers are individually responsible for data accuracy. | ||
- Rewards and penalties are proportionate to the stake assigned to each publisher. Delegators share the risks and rewards of the publisher(s) to whom they assign their stake. | ||
- A higher number of publishers for each price feed contributes positively to the security of such feed. | ||
- Staking for **OIS** is complementary to staking for **governance**, and eligible $PYTH tokens can be used for both purposes. | ||
- The ability to slash stake in OIS requires **unlocked** \$PYTH tokens, whereas staking for governance can use both locked and unlocked $PYTH tokens. | ||
- All parameter related to the OIS protocol are subject to the governance of the Pyth DAO. | ||
|
||
## Implementation | ||
|
||
OIS implements the design principles above through the following structure: | ||
|
||
1. OIS is subject to the same 7-day epoch as governance voting. All parameters used in the OIS protocol are captured at each start of the epoch on Thursdays at 0:00 UTC and remain constant until the end of the epoch. Staking into OIS is also subject to warmup and cooldown period prior and post epoch respectively. | ||
|
||
2. Each publisher is programmatically assigned a staking pool where they can self-stake and to which other stakers can delegate. | ||
- The staking pool assigned to each publisher covers all price feeds/symbols they publish. | ||
- Each staking pool has a soft cap. This soft cap dynamically expands and shrinks given the number of symbols published by the assigned publisher. | ||
- Price feeds with a low number of publishers contribute more to the cap's expansion. | ||
- Staking into the pool can exceed the soft cap. However no rewards are paid for the excess amount. On the contrary, the excess amount is subject to the penalty if the assigned publisher's data is inaccurate. | ||
- The OIS protocol prioritizes self-stake attributed to the **publisher's stake** when distributing rewards to the publisher's pool. | ||
- All staking pools charge the same delegation fee for stakers who are delegating stake to one or many pools. | ||
3. Each pool has a maximum reward rate per epoch, which applies only to the staked amount within the soft cap. | ||
4. The total amount of rewards paid to all pools is bound by the same cap relative to the amount of rewards available to the OIS protocol. | ||
5. Slashing of stake has a hard percentage cap and only impacts pools that assigned to publishers responsible for the poor data quality. Both self-stakers and delegators are also slashed proportionally to their staked amount in the impacted pools. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"mathematical-representation": "Mathematical Representation", | ||
"examples": "Examples", | ||
"slashing-rulebook": "Slashing Rulebook" | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.