Skip to content

Conversation

@Yakuhito
Copy link
Contributor

No description provided.

@OverActiveBladderSystem

So putting my fantasy hat on with a low understanding to dream of things for the pool/farm reward mechanism...

is these concepts something that could be used for farming on pools (or solos) when it comes to claiming and distributing rewards with fewer transactions, as well as flexibility in how much of the initial reward portions are committed to the pool and/or farmer?

Fantasy 1: would this allow a fancy puzzle for farmers to commit 100% (or varying amounts) of the pool/farm reward portions to a pool rather than the 87.5% / 12.5% split today?

If transaction fees in the farmer portion become the largest portion of the reward, some users will want that shared with the whole pool. So if there was an "official protocol" instead of a centralized pool making blocks for them or trusting people won't cheat a regular pool which often requires them to build up credit owed before payout, that might be neat.

Fantasy 2: would this allow stacking of multiple pool rewards and a pool can inject their (by block, by day, by fixed amount) oracle data for payouts when claiming those rewards, turning it into a single transaction? rather than claiming rewards and multiple distribution transactions after?

If the fantasy thinking is possible, would it just take a change to consensus in the upcoming hard fork to open the door to these ideas and more with flexibility going forward while we're doing the hard fork?

@danieljperry
Copy link
Contributor

CHIPs 50 and 51 are now drafts. (Both CHIPs can be handled in this PR.) Please leave your reviews here, and feel free to discuss in the #chips channel of our Discord.

@Quexington
Copy link

Left a comment PR on the reference repository: Yakuhito/slot-machine#13

@Yakuhito
Copy link
Contributor Author

Left a comment PR on the reference repository: Yakuhito/slot-machine#13

Replied. The slot puzzle no longer assumes a singleton amount of 1 and is roughly ~25% smaller.

@Yakuhito
Copy link
Contributor Author

After thinking about your ideas @OverActiveBladderSystem here's my comments:

is these concepts something that could be used for farming on pools (or solos) when it comes to claiming and distributing rewards with fewer transactions, as well as flexibility in how much of the initial reward portions are committed to the pool and/or farmer?

Fantasy 1: would this allow a fancy puzzle for farmers to commit 100% (or varying amounts) of the pool/farm reward portions to a pool rather than the 87.5% / 12.5% split today?

To change the split, you'd probably want to change consensus to allow custom or even configurable percentages. I think the same mechanism used to switch pools could work. I'm not an expert on that topic, so not the best person to ask 😅

If transaction fees in the farmer portion become the largest portion of the reward, some users will want that shared with the whole pool. So if there was an "official protocol" instead of a centralized pool making blocks for them or trusting people won't cheat a regular pool which often requires them to build up credit owed before payout, that might be neat.

This would, more likely, require a custom pooling singleton (and that to be supported at the consensus level - not sure if it is). I'm pro-official-protocol-pools, but I don't think these puzzles can necessarily help here.

Fantasy 2: would this allow stacking of multiple pool rewards and a pool can inject their (by block, by day, by fixed amount) oracle data for payouts when claiming those rewards, turning it into a single transaction? rather than claiming rewards and multiple distribution transactions after?

The distributors work on a per-second basis. The difficult 'balance' here is that pools will likely frequently update the list of active farmers and their shares of the rewards, which might also cause a lot of on-chain transactions. This contrasts the ideal case of the rewards distributor, where updates from the manager are not that frequent. The NFT reward distributor doesn't have this problem because users update it themselves when they stake/unstake an NFT, but you unfortunately can't trust farmers to update their own space. Is there an aspect of the current farming rewards distribution mechanism you'd like to see improved?

If the fantasy thinking is possible, would it just take a change to consensus in the upcoming hard fork to open the door to these ideas and more with flexibility going forward while we're doing the hard fork?

Generally no, as the CHIPs cover Chialisp puzzles that can run on the current version of the blockchain. I think a hard fork would be needed for the split idea, for example. Probably best to ask over Discord, where people with better knowledge in that area can answer.

@Yakuhito
Copy link
Contributor Author

CHIP call slides (call in 8h13m from now)

@Yakuhito
Copy link
Contributor Author

Yakuhito commented Aug 14, 2025

As suggested in the call, please find the benchmarks produced by the tests from chia-wallet-sdk below. Each action call aims to build a 'realistic' spend bundle. You can compare the values against the ones provided in the Chia Documentation, although I found the docs to be (sometimes severely) under-reporting some costs.

EDIT: With the addition of three new reward distributor modes and the release of the Rue rewrite, raw test results became a bit too long to be included in this thread. Please see this comparison, which uses the costs reported in the 'Average' benchmark column. For full data, don't hesitate to fork my current working branch of chia-wallet-sdk and run the tests yourself.

@danieljperry
Copy link
Contributor

The recording of our Zoom call for these CHIPs is now available:
https://youtu.be/4RvTy3kZdQU

@DrakoPensulo
Copy link

DrakoPensulo commented Aug 16, 2025

I think, there is a small code optimization possible in withdraw_incentives.clsp
replace
(if (= withdrawal_share (/ (* WITHDRAWAL_SHARE_BPS committed_value) 10000)) withdrawal_share (x))
with
(if (= (* withdrawal_share 10000) (* WITHDRAWAL_SHARE_BPS committed_value) ) withdrawal_share (x))

Alternatively, instead of carrying in WITHDRAWAL_SHARE_BPS carry in WITHDRAWAL_SHARE_BPS divided by 10000 and update the above line of code accordingly.

Similar optimizations can be applied to
add_incentives.clsp line 26 and the parameter FEE_BPS
new_epoch.clsp line 40 and the parameter FEE_BPS

@Quexington
Copy link

I think, there is a small code optimization possible in withdraw_incentives.clsp replace (if (= withdrawal_share (/ (* WITHDRAWAL_SHARE_BPS committed_value) 10000)) withdrawal_share (x)) with (if (= (* withdrawal_share 10000) (* WITHDRAWAL_SHARE_BPS committed_value) ) withdrawal_share (x))

Alternatively, instead of carrying in WITHDRAWAL_SHARE_BPS carry in WITHDRAWAL_SHARE_BPS divided by 10000 and update the above line of code accordingly.

Similar optimizations can be applied to add_incentives.clsp line 26 and the parameter FEE_BPS new_epoch.clsp line 40 and the parameter FEE_BPS

Are you definitely sure the * operation is less expensive than the / operation?

@DrakoPensulo
Copy link

I think, there is a small code optimization possible in withdraw_incentives.clsp replace (if (= withdrawal_share (/ (* WITHDRAWAL_SHARE_BPS committed_value) 10000)) withdrawal_share (x)) with (if (= (* withdrawal_share 10000) (* WITHDRAWAL_SHARE_BPS committed_value) ) withdrawal_share (x))
Alternatively, instead of carrying in WITHDRAWAL_SHARE_BPS carry in WITHDRAWAL_SHARE_BPS divided by 10000 and update the above line of code accordingly.
Similar optimizations can be applied to add_incentives.clsp line 26 and the parameter FEE_BPS new_epoch.clsp line 40 and the parameter FEE_BPS

Are you definitely sure the * operation is less expensive than the / operation?

Based on the cost table https://chialisp.com/costs/ it seems that it is slightly cheaper. However, I did not perform any tests. IMO, more importantly, / produces rounding error while * does not. Whether this rounding error can be exploited or not, I do not know.

The second proposed optimization. At this point a curried in parameter is divided by a constant 10000, both are known at compile time, so why not just curry in the quotient. If only integers can be curried in, this optimization cannot be applied.

@Yakuhito
Copy link
Contributor Author

Yakuhito commented Aug 20, 2025

I think, there is a small code optimization possible in withdraw_incentives.clsp replace (if (= withdrawal_share (/ (* WITHDRAWAL_SHARE_BPS committed_value) 10000)) withdrawal_share (x)) with (if (= (* withdrawal_share 10000) (* WITHDRAWAL_SHARE_BPS committed_value) ) withdrawal_share (x))
Alternatively, instead of carrying in WITHDRAWAL_SHARE_BPS carry in WITHDRAWAL_SHARE_BPS divided by 10000 and update the above line of code accordingly.
Similar optimizations can be applied to add_incentives.clsp line 26 and the parameter FEE_BPS new_epoch.clsp line 40 and the parameter FEE_BPS

Are you definitely sure the * operation is less expensive than the / operation?

Based on the cost table https://chialisp.com/costs/ it seems that it is slightly cheaper. However, I did not perform any tests. IMO, more importantly, / produces rounding error while * does not. Whether this rounding error can be exploited or not, I do not know.

The second proposed optimization. At this point a curried in parameter is divided by a constant 10000, both are known at compile time, so why not just curry in the quotient. If only integers can be curried in, this optimization cannot be applied.

The static cost difference between * and / is 11, but multiplication may have bigger dynamic cost.

Chialisp has no floats to my knowledge, which is why the puzzles use BPS and divide by 10000 on the go. The order of operations was specifically chosen to preserve as much precision as possible in the calculations. Rounding is always done in the dApp's favor (to the user's disadvantage) to prevent potential exploits.

@danieljperry
Copy link
Contributor

CHIPs 50 and 51 have a working implementation, and all comments so far have been addressed. These CHIPs are now in Review status. Please leave any final reviews here.

@Yakuhito
Copy link
Contributor Author

The NFT mode of the reward distributor has begun mainnet testing as part of the DIG Network community alpha: X post / site

@Yakuhito
Copy link
Contributor Author

Yakuhito commented Sep 3, 2025

Puzzles will be updated to use better precision for rewards: blog.fireacademy.io/p/too-discrete-to-handle-how-low-cat

@judeallred
Copy link
Contributor

judeallred commented Sep 12, 2025

Hi Yakuhito, just wanted to share some notes and feedback on your CHIP-51.

First and foremost, thanks for building this! Even in its first form this a great thing to have in the CHIA ecosystem.

I've been testing with your https://rewards.fireacademy.io/distributor/datalayer-minions

I have 106 minions staked.

After claiming, I received 75 DIG coins, each of amount 0.016, and there are more to claim. Claiming a second time...
I received 31 more coins, also of 0.016 DIG each.

It appears the rewards batch per NFT. In the single-NFT case this is good, as I receive one reward coin per claim. In the multi-nft case, it'd be nicer if I received one coin overall. At present, following a claim, I need to do a sweep operation in my wallet in order to keep the rewards manageable.

  • Would it be possible to bundle the rewards into one coin, no matter how many NFTs are staked?
  • Is it viable to adjust the claim mechanism to gather all of the rewards in one operation (instead of one-per-75)?

Next, thinking about staking mechanisms that are common in other blockchains (e.g. ETH and Solana), there are a few very common patterns that I would love to see CHIA support so that we have feature parity. Maybe those are better as future CHIPS, but to lay out the wishlist I would look for CHIA's staking mechanisms to facilitate:

  • Additional rewards of varying types to be added flexibly on a per-epoch basis. E.g. both the Jupiter (https://vote.jup.ag/) and Aethir (https://user.aethir.com/stake) staking systems use this mechanism to both accept sponsorship and cross-promote with other projects. The way it works (from a user perspective) is that in a given epoch, rewards from an ecosystem project (e.g. in Jupiter, one example is CLOUD) are seamlessly included alongside their existing staking rewards claim.

    • e.g. It'd be neat if Tang Gang could contribute HOA to a given DataLayer epoch if they wanted to. DataLayer would need to 'approve' this (or add the HOA on themselves) the so that an epoch's rewards don't get dusted or include un-desired cross-promotions.
  • The ability to stake CATs as well as NFTs. Perhaps your spec already permits this, but I would say broadly that in other ecosystems it's usually tokens that are staked rather than NFTs. This is broadly used to drive up the price of a token in the short term (/fundraise) in exchange for promising an APR on that token once staked, with the hopes that the token's project will in time become more valuable as the project succeeds.... or it's used as a sort of pump-and-dump by the creator. That said, lots of non-scam popular projects have this and used it to bootstrap their funding / reward early investors.

  • Flexibility in staking durations. I've seen a few common patterns here, including:

    • There's a fixed withdraw cooldown; Your stake is indefinite, but you can trigger an unstaking event and then your locked assets become available to you again over time. (e.g. the https://vote.sanctum.so/ staking mechanism)
    • When staking, you declare how long to stake for, and your stake's rewards receive some multiplier. For example there might be a minimum stake of 1 month which returns rewards at a 1x multiplier, or a maximum stake duration of 4 years which returns a 100x reward multiplier. ( e.g. https://docs.helium.com/governance/staking-with-helium-vote/#lockup-period )
  • Staking and rewards coupled into a DAO mechanism, where a staked position (including relevant multipliers) grants voting power in proportion to the stake and its multiplier, and epoch rewards can be scaled depending on the user's level of participation in the DAO's votes (e.g. Helium, Sanctum, and Jupiter, above)

  • [Edit: One more... ] Liquid staking tokens. (See https://learn.sanctum.so/docs/introduction-to-lsts/from-native-to-liquid-staking ). These have become popular in Solana and I'm seeing them in ETH projects now as well. The basic idea is that (translated to Chia) when I stake a CAT, I receive a different token (sCAT) as a receipt. These tokens can then trade on secondary markets, or can convert from a sCAT back to a CAT by performing the un-stake operation. If you want to liquidate your stake immediately (and the stake has a cooldown period involved), you could go on secondary market and trade sCATs for CATs directly and pay a premium. Depending on the implementation, the sCAT tokens can be used either to determine the rewards you receive when you claim, or instead claiming can be done away with entirely and instead the exchange rate of CAT <-> sCAT changes over time as the staked assets grow. (much like how your existing liquidity provider tokens work on tibetSwap).

I imagine many of these would be large efforts deserving separate CHIPs, but since you've thought through the Chialisp on this, perhaps some of these items are viable to bring into scope for this CHIP.

@Yakuhito
Copy link
Contributor Author

Yakuhito commented Feb 3, 2026

Hey, all! As I mentioned in a DM I sent @judeallred shortly after his comment, I held off responding to the last comment until the new version of the reward distributor was tested and ready to be discussed. I'll address the points below, then send another (independent) comment detailing the update. Please feel free to ask for clarifications/post new questions that may arise.

After claiming, I received 75 DIG coins, each of amount 0.016, and there are more to claim. Claiming a second time...
I received 31 more coins, also of 0.016 DIG each.

It appears the rewards batch per NFT. In the single-NFT case this is good, as I receive one reward coin per claim. In the multi-NFT case, it'd be nicer if I received one coin overall. At present, following a claim, I need to do a sweep operation in my wallet in order to keep the rewards manageable.
Would it be possible to bundle the rewards into one coin, no matter how many NFTs are staked?
Is it viable to adjust the claim mechanism to gather all of the rewards in one operation (instead of one-per-75)?

For the first question: yes! The reward distributor was initially designed for DIG, and the NFT mechanism was added as an extension. DIG mirrors would only have one entry ('ticket'), while, in the first version of the NFT reward distributor, each NFT acted as its own, independent entry. I severely underestimated the number of people holding 10+ NFTs of a given collection. With the new version, multiple NFTs (or CATs, more on that later) can be consolidated into the same entry - there will be one 'ticket' per user, not per NFT. This means you'll be able to get your payout in one coin only, with no real disadvantages other than slightly more complex staking/unstaking code.

For the second question: limits were set so spend bundles do not reach the maximum cost allowed for mempool items (5.5 billion - half a block). Now that payouts are done in a single coin for all your NFTs, you won't come near that limit - so you'll get all your rewards in one claim. A lot of users have asked for this, and I'm glad the new version of the reward distributor will have a much better experience. The only operation where you'll still have to do 'batches' is staking and unstaking - unfortunately, moving NFTs around is really expensive, so I don't think you'll be able to stake (or even transfer) 103 NFTs in a single block. Still, I think work on the drivers/frontend could improve the experience on that front (e.g., upload 5 offers one after the other, and the site automatically tries to stake one batch per block until the queue is empty).

e.g. It'd be neat if Tang Gang could contribute HOA to a given DataLayer epoch if they wanted to. DataLayer would need to 'approve' this (or add the HOA on themselves) the so that an epoch's rewards don't get dusted or include un-desired cross-promotions.

For the purpose of this CHIP, only one reward token is allowed per reward distributor. While it's possible to have more than one token, it would require a big architectural change. If the demand is there, a future reward distributor version could be built to allow this along with a new CHIP.

A lot of distributors may work with just one reward token, and assuming one reward token only allowed me to make a lot of optimizations in the current code. It may make sense to still have them run with the current standard, and then anyone who wants to take sponsorships in another token could use the other standard (which would be more costly given the increased complexity). Much like it makes sense to separate asset-asset partial offers from multi-asset ones, I think this distinction is important here as well.

The ability to stake CATs as well as NFTs. Perhaps your spec already permits this, but I would say broadly that in other ecosystems it's usually tokens that are staked rather than NFTs. This is broadly used to drive up the price of a token in the short term (/fundraise) in exchange for promising an APR on that token once staked, with the hopes that the token's project will in time become more valuable as the project succeeds.... or it's used as a sort of pump-and-dump by the creator. That said, lots of non-scam popular projects have this and used it to bootstrap their funding / reward early investors.

To quote AI, "You're absolutely right!" - the new version of the reward distributor has a mode where you can stake CATs to earn rewards. The main use case I see for this type is allowing projects to incentivize TibetSwap liquidity, but I'm sure the community will come up with entirely new ways to use this primitive.

Flexibility in staking durations. I've seen a few common patterns here (...)

Really appreciate the examples you're providing! All the modes included in this new CHIP will allow the users to unstake assets at any time. That said, at the Chialisp level, there is an easy way to add these kinds of timed locks via custom locking/unlocking puzzles. In short, you'd only have to write the locking/unlocking puzzles for a distributor that locked tokens according to the rules you mentioned above - you could then reuse most of the code of the current distributors (slot consolidations, payouts, accounting, etc.).

Staking and rewards coupled into a DAO mechanism, where a staked position (including relevant multipliers) grants voting power in proportion to the stake and its multiplier, and epoch rewards can be scaled depending on the user's level of participation in the DAO's votes (e.g. Helium, Sanctum, and Jupiter, above)

DAOs on Chia are another beast (see CHIP-0024), and definitely a major undertaking. I think reward distributors could remain mostly independent and make this scenario possible by having the DAO mechanism designed around them. It seems it would only require custom locking/unlocking puzzles. Each action already produces announcements - right now, users use those to secure the bundle, but dApps may as well use them to assert certain operation were done on the distributor.

Liquid staking tokens.

These are actually very interesting! The fact that the entries become fungible (sTokens instead of users each having a 'ticket' to reclaim staked assets) means the reward distributor is not ideal for them, but you could use something extremely similar, as the reward 'accumulation' mechanism (which I wrote about here) is the same. Honestly, this sounds like a really exciting project from a technology point of view.

I imagine many of these would be large efforts deserving separate CHIPs, but since you've thought through the Chialisp on this, perhaps some of these items are viable to bring into scope for this CHIP.

Once again, thank you very much for the interesting ideas! Your comment heavily influenced the decision to generalize locking/unlocking into puzzles to keep reward distributor flexible so that future extensions will require minimal work (specifically timed locks). While some features are addressed by the new version (slot consolidation/CAT reward distributors), the line between this CHIP and future ones needs to be drawn somewhere. The reward distributor in particular is a very complex dApp where every new feature needs careful design, optimization, testing, and reviews - while all the cases you mentioned are very interesting, I think we should be very wary with scope creep, as any new feature would require a lot of effort. That said, I think this next deployment will show the capabilities of the general system on Chia, and I hope it will inspire everyone to keep building on top of this CHIP.

@Yakuhito
Copy link
Contributor Author

Yakuhito commented Feb 3, 2026

Hey, all! We're excited to announce the 2nd generation of reward distributors, with some awesome new features:

  • Precision fix: Internal accounting now amplifies CAT amounts by u64::max (2^64 - 1). This is essentially the same as using CATs with ~19.26 more decimals. Note the amounts will get rounded down when rewards are claimed or when assets are unstaked. For example, if you have 0.1238 pending reward CATs, you'll get 0.123 CATs if you claim rewards, with the 0.0008 CAT debt being marked to be re-distributed. Similarly, if you unstake assets while your virtual balance is <0.001 CATs, that virtual balance will be given back to the distributor to allocate to all other participants in the remainder of the epoch (you won't get a payout, and you won't get it back if you restake assets).
  • Position consolidation: One commonly requested feature in the alpha deployment was the ability to get your payout in a single coin. This was not possible in V1, as every NFT was a unique position that the user holds. This ultimately led to slower lookup times for position (O(n) requests instead of O(1)) and more on-chain transactions for people with big stakes, who needed to combine their earned coins before transacting with them. The new version of the distributor allows users to consolidate many NFTs/CATs into only one position, solving this issue entirely. This feature is available to all the modes described below.
  • New NFT Modes: While only allowing NFTs minted by a particular DID to be staked into a given distributor and treating them equally has many use cases (e.g., DataLayer Minions), we realized that a more nuanced approach to NFT whitelisting and weighting can significantly expand the usage of the reward distributor to many community projects. The old NFT mode is now called 'Collection NFT' mode in order to highlight its mechanism: the collection NFT reward distributor allows any NFT from the collection (or with the same DID) to be staked and treated equally. With the new release, we're introducing the 'Curated NFT' mode, which allows curators to fully control which NFTs may be staked in a distributor and how they should be weighted. This is done by managing a datastore containing all whitelisted NFT ids and their respective weights - this datastore may be mutable (curator can update the list) or immutable (owner set weights and then locked themselves out - datastore may only be spent in oracle mode).
  • NFT Refresh: A curated NFT reward distributor may be refreshable. If an NFT weight is changed in the datastore while the said NFT is staked, anyone can restake the affected NFT to 'refresh' its weight to the new value. This would presumably be done by the datastore owner as soon as the list is updated, but any observers can trigger this refresh if that does not happen - as long as the NFT's shares in the distributor do not match those recorded in the datastore. Refresh-ability is an immutable attribute set at launch, just like the reward distributor mode - curators may opt out of this behavior at deployment by setting the distributor up as 'non-refreshable'
  • CAT Mode: The new reward distributor architecture is very flexible. If the curated NFT mode expands possible applications vertically, allowing CATs to be staked instead of NFTs expands functionality horizontally. CAT reward distributors unlock the number 1 use case of reward distributors on other chains - liquidity farms. Imagine a scenario where liquidity providers stake their TibetSwap LP tokens for additional rewards from the token issuers themselves. The CAT reward distributor unlocks this scenario, and much more. Note that the current version of the distributor allows stakers to withdraw their locked CATs at any time.
  • Rue Rewrite: All the puzzles in these CHIPs have been rewritten in Rue, which led to significant cost reductions. You can see the comparison here. Shout out to @Rigidity for updating the Rue compiler to include more optimizations, as well as double-checking the code personally!

Tests are now passing for the new version! As there is a lot of new code, we're aiming to go through another security review before proceeding to an alpha/pilot of the new reward distributor in collaboration with multiple ecosystem projects. If you're interested in being part of the new alpha test, please reach out!

We're extremely excited about the reward distributor, and expect it to impact a big part of the current and future Chia ecosystem.

@danieljperry
Copy link
Contributor

As @Yakuhito mentioned, CHIP-51 has undergone a major update. Please review both CHIPs 50 and 51 at your convenience. These CHIPs will remain in Review status until they have received another security review, as well as any reviews that come in from the community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants