Instructions
This is a high level instruction set for the Pye Core V1 Solana program. It leaves out some details and math that can be found in the white paper.
Summary
High level context: Pye Core creates yield tokens (YSOLs) and principal tokens (PSOLs). As discussed previously in this Notion space, PSOLs are simple, they are always equal to 1 SOL at maturity. Then the entirety of the yield earned for the duration of a given bond, is split evenly amongst all YSOLs (after maturity).
The amount of YSOLs minted per SOL deposited is a function of time relative to a bond’s issuance and maturity timestamp. A deposit at the issuance timestamp is 1 YSOL/$SOL and function decays linearly to 0 YSOLs/$SOL at maturity.
State
GlobalSettings
- stores the protocol fee wallet and different fee amounts.
Bond Types
StakePoolBond
- A bond that splits principal and yield from a SPL StakePool LST.SoloValidatorBond
- A bond that designates SOL and staked SOL to a single validator node. Splits principal and yield that is generated from it’s stake to that single node.msolBond
- A bond that splits principal and yield from mSOL. It requires it’s own implementation because mSOL does not use the SPL StakePool program.
Instruction Set
InitializeGlobalSettings
Initializes the GlobalSettings
state with the passed keys and fee rates.
UpdateFeeSettings
[FeeAdmin must sign] Updates the GlobalSettings
state with the passed fee wallet, fee admin, and fee rates.
StakePoolBond
InitializeStakePoolBond
Initializes a new StakePoolBond
given the stake pool, issuance timestamp, maturity timestamp, and PSOL and YSOL metadata.
Deposit
Handles depositing an LST into the StakePoolBond
and mints PSOLs and YSOLs to the depositor.
DepositSol
Allows user to deposit SOL to a StakePoolBond
and mints PSOLs and YSOLs to the depositor. The instruction will call DepositSol on the SPL Stake pool, to mint the LST and store those in the bond’s vault.
DepositSolMsol
Same as DepositSol above, but expects an mSOL bond and makes a CPI to the marinade-finance program.
RedeemPSOL
Allows a user holding PSOLs to burn their PSOLs in exchange for the LST.
Note: At maturity, the LST:SOL exchange rate is calculated and cached on the RedemptionCache
structure of the StakePoolBond
. The PSOL : LST exchange rate is determined by the amount of LSTs that equaled 1 SOL at that point in time. So PSOL holders that wait or forget to redeem immediately, are not giving up any LST backed yield.
RedeemYSOL
Allows a user holding YSOLs to burn their YSOLs in exchange for the LST.
Note: As mentioned in RedeemPSOL, the LST : SOL exchange rate is cached after the bond’s maturity date. YSOLs will maintain their same YSOL : LST exchange rate from the time of maturity.
SoloValidatorBond
InitializeSoloValidatorBond
Initializes a new SoloValidatorBond
given the validator’s vote key, issuance timestamp, maturity timestamp, and PSOL and YSOL metadata.
DepositSol
Allows the user to deposit SOL and mints PSOLs and YSOLs to the user.
This instruction uses a transient_stake_account tied to the bond to stake the received SOL. If there is an existing transient stake that is:
activating - the SOL is added to it
fully activated - the activated stake is merged into the bond’s core stake account, and a the transient stake account is reinitialized with the newly deposited SOL.
DepositStake
Allows the user to deposit a stake account.
If the bond’s stake account is fully active, which will be the majority of cases, then the user’s stake account must be fully activated.
HandleMaturity
Must be called after a SoloValidatorBond
has matured and before anyone can redeem their PSOLs or YSOLs.
This instruction makes sure the transient stake account has been merged, if needed.
RedeemPSOLForStake
User burns their PSOLs in exchange for a fully active stake account.
Note: The user must redeem for at least 1 SOL worth of PSOLs due to Solana stake program minimum delegation limits. User should use ReedemPSOLForSol if redeeming for less than the minimum.
RedeemYSOLForStake
User burns their PSOLs in exchange for a fully active stake account.
Note: The user must redeem for at least 1 SOL worth of YSOLs due to Solana stake program minimum delegation limits. User should use ReedemYSOLForSol if redeeming for less than the minimum.
RedeemPSOLForSol
User transfers PSOLs to the contracts GlobalCounterParty in exchange for SOL.
This allows the user to get their SOL immediately without having to meet the 1 SOL minimum delegation.
RedeemYSOLForSol
User transfers YSOLs to the contracts GlobalCounterParty in exchange for SOL.
This allows the user to get their SOL immediately without having to meet the 1 SOL minimum delegation.
CounterPartyRedeemPSOL
[Permissionless] GlobalCounterParty burns it’s PSOLs in exchange for SOL in the bond’s liquid reserve.
CounterPartyRedeemYSOL
[Permissionless] GlobalCounterParty burns it’s YSOLs in exchange for SOL in the bond’s liquid reserve.
CounterPartyUpdateLiquidReserve
[Permissionless] [after maturity] uses the transient stake account to unstake from the bond’s main stake account and move that SOL into the bond’s liquid reserve.
This instruction will only unstake enough SOL to meet the needs of the GlobalCounterParty’s PSOLs and YSOLs for that bond.
CounterPartyWithdrawSol
[FeeAdmin is signer] Allows the FeeAdmin to withdraw SOL from the global counter party.
Limitations / Potential improvements
SoloValidatorBonds
[No req to handle this case at present] There is no ability to deposit a stake account that has a Stake program defined lockup. When Solana foundation sells locked $SOL OTC, it uses these lockups to enforce the lock duration while still transferring stake or withdraw authority to the purchaser.
Accepting these types could possibly be achieved if a Bond’s core stake account also enforced a lockup on the exact same date time. More research would be needed to confirm this assumption.
Last updated