PI-1: Convert Newly Earned Pinto and Misc. Bug Fixes
Executed on November 27, 2024 at 05:52 UTC.
Summary
- Germination of Earned Pinto: Eliminate the Germination Period for Earned Pinto, enabling Pinto → LP Converts immediately after a Farmer Plants their Earned Pinto.
- Re-germination of Converted Deposits: Eliminate a bug where Converts can erroneously cause a Deposit to Germinate again.
- Minimum Crop Ratio During Rain: Add a distinct Minimum Crop Ratio while the system is Raining.
- Initial Soil Supply: Add
initialSoilto expose the remaining Soil supply before Morning Auction scaling.
- Event and Rain Data Fixes: Correct the number of Pinto emitted by the
Sowevent andstartRain’s emitted Crop Ratio change.
- Plenty Claim Return Values: Return the number of tokens claimed as Plenty from
claimPlentyand the token addresses and numbers of tokens claimed fromclaimAllPlenty.
Links
- Implementation Commit: d3d412c3d5af2d8cf654f72d378d3c826675c5fd
Problems
1. Germination of Earned Pinto
Earned Pinto Deposits should be able to be used in a Pinto → LP Convert immediately upon distribution (i.e., they should not Germinate). However, when a Farmer Planted their Earned Pinto, they were not able to Convert their new Pinto Deposit to an LP token Deposit until 2 Seasons elapsed. This inability to Convert immediately after Planting was a significant inefficiency with respect to peg maintenance because users that just Planted their Earned Pinto needed to wait until the Germination Period ended and then return to the Farm to Convert their Pinto for peg maintenance.
2. Re-germination of Converted Deposits
When a Farmer Converted a Pinto Deposit that had recently finished Germinating to an LP token Deposit (or vice versa), the output Deposit became Germinating again. In this case the then Germinating Deposit lost its Stalk, and instead was issued Germinating Stalk (i.e., a claim on Stalk after the Germination Period ends). Germinating Stalk is ineligible for mints or Flood rewards. Thus, a user was disincentivized to Convert during times of large mints and Floods because they would lose 2 Seasons of mints and eliminate their share of subsequent Flood distributions during the current Rain associated with the Converted Deposits.
3. Minimum Crop Ratio During Rain
When the system is Raining, the minimum Crop Ratio should be lowered to increase the incentive to Convert from Deposited Pinto to the Deposited LP token with the most Seeds.
4. Initial Soil Supply
There was no on-chain function that returned the remaining Soil supply before Morning Auction scaling, so the UI had to make excessive RPC calls to reconstruct it.
5. Event and Rain Data Fixes
The Sow event emitted an incorrect number of Pinto, and startRain did not correctly emit the change in BeanToMaxLpGpPerBdvRatio, resulting in incorrect data in the subgraph.
6. Plenty Claim Return Values
The claimPlenty and claimAllPlenty functions did not return sufficient data to easily compose transactions together in the UI.
Solutions
1. Germination of Earned Pinto
Update the plant function to issue a non-Germinating Pinto Deposit crediting it with the Grown Stalk it would have earned at the previous Season's Seeds per PDV for Pinto, plus an additional 1 micro Seed.
2. Re-germination of Converted Deposits
Update the convert function to issue a non-Germinating token Deposit for Pinto ↔ LP Converts if the value being Converted was not Germinating. If the resulting Deposit would otherwise have a Germinating Stem, top up Grown Stalk to the non-Germinating minimum based on the previous Season's Seeds per PDV of the output token, plus an additional 1 micro Seed.
3. Minimum Crop Ratio During Rain
Add rainingMinBeanMaxLpGpPerBdvRatio to the EvaluationParameters struct in storage and initialize the value to 33333333333333333333 (approximately 33.33%), and update getBeanToMaxLpGpPerBdvRatioScaled to use rainingMinBeanMaxLpGpPerBdvRatio instead of minBeanMaxLpGpPerBdvRatio when the system is Raining.
4. Initial Soil Supply
Add the initialSoil function, which returns s.sys.soil.
5. Event and Rain Data Fixes
Update the Sow event to properly emit the number of Pinto that were used to Sow, rather than the number of Soil deducted from s.sys.soil.
Update the startRain function in LibFlood.sol to properly emit the change in BeanToMaxLpGpPerBdvRatio.
6. Plenty Claim Return Values
Update the claimPlenty function to return the number of tokens claimed. Update claimAllPlenty to return the token addresses and numbers of tokens claimed.
Rationale
1. Germination of Earned Pinto
There is no reason to enforce a Germination Period for newly Planted Earned Pinto Deposits. The Germination Period prevents a specific manipulation. Without it, a user could Deposit value in the Silo to receive Stalk, call the gm (which triggers the Sunrise), and then immediately withdraw the Deposit plus the yield from that Sunrise, all without holding exposure to the price of Pinto. Earned Pinto already accrued from a Deposit that completed Germination, so exempting it does not enable the manipulation described above.
The inability to Convert newly Planted Pinto to Deposited LP tokens is a significant inefficiency with respect to peg maintenance because it creates a lag between when Farmers Plant their Pinto and when they can Convert them. This lag may delay the effect of mint distributions on peg maintenance with respect to the value that stays in the protocol (i.e., wasn’t sold) by at least one Season, because delayed Converts can delay the peg recovery and lead to more Pinto being minted.
2. Re-germination of Converted Deposits
Once value that was Deposited in the Silo has completed its Germination Period, there is no reason to make it Germinate again upon a Convert because the value will have already been in the Silo for a sufficient period of time, ensuring that it is not taking advantage of a Pinto mint without holding exposure to the Pinto price.
The ability to Convert a non-Germinating Pinto Deposit into a Germinating LP token Deposit creates a disincentive to Convert, which can lead to excess mints because holders that would otherwise have Converted do not.
3. Minimum Crop Ratio During Rain
When it's Raining, Pinto should be very aggressive in incentivizing Converts from Pinto Deposits to LP token Deposits. During a Flood, the protocol should be minimizing how much it mints because when the Flood ends it will almost certainly experience heavy outflows. Accordingly, lowering the Crop Ratio to an exceptionally low value – below the Minimum Crop Ratio – will create a stronger incentive for Depositors to Convert their Deposited Pinto to LP token Deposits and minimize excessive minting.
4. Initial Soil Supply
Exposing the remaining unscaled Soil directly lets the UI read the protocol’s current value without reconstructing it through multiple RPC calls.
5. Event and Rain Data Fixes
Emitting the Pinto actually Sown and emitting the Crop Ratio change allows the subgraph and UI to process the protocol’s state changes accurately.
6. Plenty Claim Return Values
Returning the claimed token addresses and numbers of tokens lets the UI use claim results when composing subsequent actions in the same transaction.
Contract Changes
Initialization
InitPI1.init() was called at 0x4cbD1A8ff8E3dcE759dC9049417DeeBC3Ac24ddA to initialize rainingMinBeanMaxLpGpPerBdvRatio to 33333333333333333333 (approximately 33.33%).
Facet Changes
Other Contract / Parameter Changes
Introduced a separate minimum Crop Ratio during Rain of approximately 33.33%, using rainingMinBeanMaxLpGpPerBdvRatio. Outside Rain, getBeanToMaxLpGpPerBdvRatioScaled continues to use minBeanMaxLpGpPerBdvRatio. Previously, the 50% minimum also applied during Rain. The minimum remains 50% outside Rain. Ratios use 18 decimal places per percentage point (100e18 = 100%).
Externally linked library deployments changed as follows (previous → new). These address changes do not by themselves imply changes to each library’s behavior.
ApprovalFacet, ConvertGettersFacet, SiloGettersFacet, GaugeGettersFacet, and FieldFacet have no externally linked libraries.
Function Changes
- Updated
plantand Pinto ↔ LPconvertbehavior to produce non-Germinating Deposits.plantnow returns the non-Germinating Stem instead of the current Stem tip.
- Added
getHighestNonGerminatingStem(address)andgetHighestNonGerminatingStems(address[])to expose the highest non-Germinating Stem for one or more tokens.
- Removed obsolete special handling for Earned Pinto in withdrawal and transfer accounting in
TokenSiloandLibSilo, consistent with Planted Deposits now receiving a non-Germinating Stem.
- Added internal helpers in
LibGerminate,LibTokenSilo, andLibConvertto calculate the highest non-Germinating Stem and the minimum Grown Stalk needed to prevent re-germination.
- Updated
LibTokenSilo.calculateStalkFromStemAndBdvto returnuint256and perform the BDV multiplication as unsigned 256-bit arithmetic.
- Updated
LibGauge.getBeanToMaxLpGpPerBdvRatioScaledto use the Rain-specific minimum Crop Ratio while Raining.
- Added
initialSoil()to returns.sys.soil.
- Updated
claimPlentyto return the number of tokens claimed andclaimAllPlentyto return an array of token addresses and numbers of tokens claimed.
Event Changes
- Added a
StalkBalanceChangedemission whenplantmints the Grown Stalk credited to the newly Planted Deposit, reporting the additional active Stalk and Roots.
- Corrected the number of Pinto emitted by
Sowto reflect the number of Pinto Sown rather than the scaled Soil deducted.
- Corrected the Crop Ratio change emitted by
startRain. EmittedBeanToMaxLpGpPerBdvRatioChangebefore resetting the stored ratio to zero.