Skip to content
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

SIP-31: Fungible StakeSui objects #31

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

0xripleys
Copy link
Contributor

No description provided.

@amogh-sui
Copy link
Contributor

Hey @0xripleys I'm the editor for this SIP- can you please share the write access to this repo with amogh-sui ?

@0xripleys
Copy link
Contributor Author

@amogh-sui invited!

@0xripleys 0xripleys changed the title SIP: allow StakedSui objects to be merged together across different epochs SIP: Fungible StakeSui objects May 31, 2024
@amogh-sui amogh-sui changed the title SIP: Fungible StakeSui objects SIP 31: Fungible StakeSui objects May 31, 2024
This is possible and I really like this idea. The main benefit of doing this is that it would immediately enable single-validator LSTs for the entire validator set, which would be pretty cool.

The tricky part would be managing a unique Coin type + metadata per StakingPool. Some notes:
- We would need a one time witness per StakingPool to create the Coin type. This can be passed into the StakingPool on instantiation.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right OTWs are only available in init function at package publishing times so I'm not sure if this solution is feasible without making some OTW exceptions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An idea: can we leverage TTO to support this for both newly created and existing StakingPool objects? E.g.,

Add something like:

public fun add_lst_coin<T>(cap: Receiving<TreasuryCap<T>>, metadata: Receiving<T>, pool: &mut StakingPool) {
  // assert cap.total_supply == 0 to ensure there has not been any preminting
  // add cap to pool.extra_fields["lst_cap"], which ensures this is the only coin type associated with this pool
  // update CoinMetadata fields to whatever standards we want for LST tokens
  // share metadata
}

to staking_pool, and then anyone can publish a package that calls create_currency in the initializer, then transfers the TreasuryCap and CoinMetadata to the StakingPool object.

This is a bit different than the idea of calling create_currency inside staking pool, but it won't require OTW exceptions (which are a bit scary), and I think it satisfies the requirements of making this permissionless + compatible with existing StakingPool's

Copy link
Contributor Author

@0xripleys 0xripleys Jun 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, after prototyping an LST on top of my reference implementation I'm kind of against making this a Coin, as I would not be able to store Coins from different validators together in the same vector. This is needed to efficiently do unstake operations (LST -> vector<StakedSui>). If we made FungibleStake a Coin, I would have to do a linear amount of dynamic field reads which doesn't feel good

@amogh-sui amogh-sui added active Active SIPs that are either in Draft, Review, Fast Track or Last Call status. labels Jun 14, 2024
@admin-aftermath
Copy link
Contributor

Is there a public implementation of convert_to_fungible_stake and does it adhere to the activation epoch of the StakedSui object?

@0xripleys
Copy link
Contributor Author

Is there a public implementation of convert_to_fungible_stake and does it adhere to the activation epoch of the StakedSui object?

Yes, https://github.com/0xripleys/sui/pull/1/files#diff-949230cb51ab41017ae722aede9a6e4902b73034f251f6953c161254a739cbf0R230

@kklas
Copy link
Contributor

kklas commented Jun 17, 2024

Hey sorry for the stupid question I'm not very familiar with the staking system. IIUC this will make it possible to merge different stake objects for the same validator but across different epochs? What makes these different objects fungible? Considering there's an activation period of 1 epoch and then another 1 epoch before they start earning rewards, are these newly created stake objects fungible with the other objects that are already earning rewards?

@admin-aftermath
Copy link
Contributor

Hey sorry for the stupid question I'm not very familiar with the staking system. IIUC this will make it possible to merge different stake objects for the same validator but across different epochs? What makes these different objects fungible? Considering there's an activation period of 1 epoch and then another 1 epoch before they start earning rewards, are these newly created stake objects fungible with the other objects that are already earning rewards?

StakedSui objects are only fungible with other StakedSui objects (1) from the same pool id and (2) with the same activation_epoch. This leads a growing number (n x m) of StakedSui objects (where n is the number of validators and m is the number of epochs) for any protocol that wants to maintain StakedSui (e.g. any LSD).

This SIP addresses that issue by being removing the restriction of (2) and letting you join FungibleStake that are beyond their activation_epoch.


/// An FungibleStake object with a value of 1 corresponds to 1 pool token in the Staking pool.
/// This can be a Coin! See the Rationale below.
public struct FungibleStake has key, store {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: I would favor FungibleStakedSui or ActivatedStakedSui to keep the naming schema the same between this object and StakedSui.

@kklas
Copy link
Contributor

kklas commented Jun 17, 2024

This SIP addresses that issue by being removing the restriction of (2) and letting you join FungibleStake that are beyond their activation_epoch.

That makes sense, thanks for the clarifiaction! Just to confirm my understanding -- this means that in general you will hold 2 objects, one for staked sui that's pending activation and another fungible one that you merge the activated ones into?

@0xripleys
Copy link
Contributor Author

That makes sense, thanks for the clarifiaction! Just to confirm my understanding -- this means that in general you will hold 2 objects, one for staked sui that's pending activation and another fungible one that you merge the activated ones into?

yep!

@admin-aftermath
Copy link
Contributor

That makes sense, thanks for the clarifiaction! Just to confirm my understanding -- this means that in general you will hold 2 objects, one for staked sui that's pending activation and another fungible one that you merge the activated ones into?

n x 2 objects since both StakedSui and FungibleStake are distinct per staking pool / validator.

public fun fungible_stake_to_sui_amount(pool: &StakingPool, fungible_stake_amount: u64): u64;
public fun sui_to_fungible_stake_amount(pool: &StakingPool, sui_amount: u64): u64;

public fun join_fungible_stake(self: &mut FungibleStakedSui, other: FungibleStakedSui);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great SIP overall!

Can we add method aliases for the join_fungible_stake and split_fungible_stake functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, can definitely do that.

@wriches wriches changed the title SIP 31: Fungible StakeSui objects SIP-31: Fungible StakeSui objects Aug 8, 2024
emmazzz added a commit to MystenLabs/sui that referenced this pull request Sep 27, 2024
## Description 

Implementation for sui-foundation/sips#31

## Test plan 

Unit tests + random tests for the math

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
- [ ] REST API:

---------

Co-authored-by: Emma Zhong <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
active Active SIPs that are either in Draft, Review, Fast Track or Last Call status.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants