PI-10: Fix Cultivation Gauge and Revise Parameters

Executed on June 19, 2025 at 03:57 UTC.

Summary

  1. Cultivation System: Upgrade the Cultivation System to handle two edge cases.
  1. Soil Sold Out Threshold: Upgrade the mechanism that determines if Soil sells out to be more manipulation resistant.
  1. Convert Down Penalty: Update the Convert Down Penalty Gauge to issue the penalty as a function of instead of .
  1. Batch Plot Transfers: Restore batch Plot transfers with correct allowance checks.
  1. Plot Listing Payments: Prevent Plot Listings from being filled with zero Pinto and correct the rounding boundary.

Links

Problems

1. Cultivation System

With the introduction of Tractor support for Sowing, there was an inefficiency discovered in how the Cultivation System worked.

In particular, the Cultivation Factor decreased when Soil did not sell out. In instances where there was a Tractor Requisition to Sow at the Maximum Temperature in a Season in which Soil sold out, and there were no Tractor Requisitions to Sow at lower Temperatures, the Cultivation Factor got "stuck" oscillating at the level it was prior to the Tractor Requisition being filled (typically the minimum Cultivation Factor). The result was that the available Soil never increased, even if there was demand to Sow in excess of the available Soil. In practice this had resulted in the Field never offering enough Soil to meaningfully affect the state of the system.

Additionally, there was no Steady case in which the Cultivation Factor stayed the same, which could lead to suboptimal numbers of Soil being issued in the instance where there was a consistent amount of demand for Soil across multiple Seasons.

2. Soil Sold Out Threshold

The threshold at which the protocol considered Soil to be sold out was not manipulation resistant.

3. Convert Down Penalty

The Convert Down Penalty was insufficiently aggressive in instances where the L2SR was Reasonably Low.

4. Batch Plot Transfers

A bug in the protocol allowed a malicious actor to bypass the approval process and transfer another user's Plots without their permission. The vulnerable functionality was removed in an Emergency PI leaving users unable to transfer multiple Plots in a gas efficient way.

5. Plot Listing Payments

A bug in the protocol allowed small Plot Listings (podAmount <= 1e6) with a certain Pod price to be purchased without Pinto.

Solutions

1. Cultivation System

Introduce a new threshold in which the protocol considers Soil mostly sold out.

Set the "Mostly Sold Out" threshold as a function of the Soil issued at the start of the Season, , and the Sold Out threshold (see below):

.

Introduce the Cultivation Temperature, which is set at the previous Season’s Maximum Temperature when Soil is Sold Out or Mostly Sold Out, and demand for Soil is steady or increasing.

Update the Cultivation Factor Gauge to increase, stay the same, or decrease based on the following logic: increase when Sold Out. Remain unchanged when Mostly Sold Out, or when demand is decreasing and the previous Season’s Maximum Temperature is below the Cultivation Temperature. Decrease otherwise. The Cultivation Factor remains between 1% and 100%.

2. Soil Sold Out Threshold

Update the "Sold Out" threshold to be a function of Soil issued at the start of the Season, , as:

3. Convert Down Penalty

Update the Convert Down Penalty such that the penalty is a function of , rather than . Here, denotes the previous Season’s L2SR, the lower bound (12%) replaces the optimal bound (40%), is the rolling counter after its current update, and is its cap of 12. The counter increases by 1 when time-weighted deltaB is positive and decreases by 1 otherwise, bounded between 0 and 12. At zero L2SR, the prior penalty ratio is retained instead of using this formula. The penalty is waived when the Pinto price in the conversion Well exceeds the Excessively High Price threshold. A minimum number of Grown Stalk is retained to keep the converted Deposit from germinating.

4. Batch Plot Transfers

Reintroduce the transferPlots function to properly decrement the allowance of a sender when sending another Farmer's Plot(s).

5. Plot Listing Payments

Update the fillPodListing function to revert when a user attempts to fill a Listing with 0 Pinto. Tighten the remaining-Pod rounding comparison to prevent an entire additional payment unit from being rounded away.

Rationale

1. Cultivation System

The Cultivation Factor getting stuck such that it never increases effectively cripples the efficacy of the Field. By tracking the Cultivation Temperature the protocol is able to prevent itself from getting stuck and reenables the Field to meaningfully contribute to peg maintenance.

Introducing a Steady case to the Cultivation Factor changes means that the protocol can more granularly adjust the number of available Soil, leading to even more efficient Soil issuance.

2. Soil Sold Out Threshold

Prior to this upgrade Soil was considered Sold Out if at most one Soil was not sold. Because the number was so low, there was the potential for manipulation that could prevent the protocol from logging Soil being Sold Out by someone Sowing all but just over 1 Soil.

When initial Soil is at least 50, less than 5 Soil remaining qualifies as Sold Out. With low gas costs, a Farmer with demand is likely to Sow the remaining Soil. When initial Soil is at least 500, the threshold is capped at 50 Soil. The cap was chosen to leave enough value that a Farmer with demand is expected to find Sowing worthwhile, while avoiding a threshold that grows indefinitely with Soil issuance.

3. Convert Down Penalty

By changing the Convert Down Penalty to be 100% when the counter is zero, the Pinto price in the conversion Well does not exceed the Excessively High Price threshold, and the L2SR is at least the Excessively Low L2SR threshold instead of the Optimal L2SR threshold, the protocol will have at least one Season where the penalty will be 100% in more instances when the Pinto price crosses the value target. This should cause TWA∆P > 0 and a mint to occur, which in instances where the L2SR is not Excessively Low would generally be healthy for the protocol. A 100% penalty does not burn all Grown Stalk. The minimum retained Grown Stalk keeps the converted Deposit from germinating.

4. Batch Plot Transfers

Correct allowance accounting restores batch transfers while requiring a delegated sender to have sufficient approval for the total number of Pods transferred.

5. Plot Listing Payments

Requiring a positive payment prevents a zero-Pinto fill. The stricter rounding boundary prevents an entire additional payment unit from being rounded away.

Contract Changes

Initialization

Executed InitPI10.init() at 0xcc7578d84785c30a45306c8afc75955ba1767709. Extended the Cultivation Gauge data from four to six uint256 values, preserving its existing adjustment and factor bounds and initializing cultivationTemp and prevSeasonTemp to zero. The stored Cultivation Factor and Convert Down Penalty value were unchanged by initialization. The new stored initialSoil field was not populated by the initializer. Both new threshold getters returned zero at the execution block, before the next Sunrise stored the new Season’s initial Soil.

Facet Changes

Replaced four facets and added five selectors: two Soil threshold getters, two Gauge-result getters, and the restored transferPlots function. Other selectors in these facets were replaced without implying that every function changed.

FacetActionPrevious ImplementationNew Implementation
GaugeFacetAdd / Replace0x42575b2f01d18cf3ed670c9fe82ee90332739d030x046c76aee5d109fba8708ee58a50d76eea1f98dc
SeasonFacetReplace0x5545a4ab5cd3f6e7db0883e73ea4805f6e1270a90x9c74f623d22c4132211c9a8c605de7d2cda01700
FieldFacetAdd / Replace0x0b5888a4c6fb90d26fb4d5f782d45c9e86dcc9740x36e4dd6f2be854962174c3e398cd0e11d49e404c
MarketplaceFacetAdd / Replace0x1f4504295c5bd57cdbd8caf4df9ab13381cb0ad40x5aeb7c0a256b167bae026056d32818539b1734b4

Other Contract / Parameter Changes

SeasonFacet linked the libraries listed below. GaugeFacet, FieldFacet and MarketplaceFacet have no externally linked libraries. LibEvaluate changed demand classification. LibWeather is a new external dependency containing the Temperature logic and the previous-Season Temperature update. The other six libraries have new deployment addresses but unchanged own-source files. Shared compiled dependencies may still differ.

LibraryPrevious ImplementationNew ImplementationUsed By
LibEvaluate0x311877f9ffbaf12b905df3e1f8c3b5f3c5527bd40x1687f3eccced54e4ea4d98ffa13e2108954501e5SeasonFacet
LibGauge0x28d436b9bbbe755dea4db747483f693d718479840xfa27f1b255a02a929a7a4e668066ce76cadcc09cSeasonFacet
LibIncentive0x09240a6c83350caaf110d9de6e23a659625d54760xb3f71bf8362cbaafebb99e1e5fac02c85e1ecfccSeasonFacet
LibShipping0x3e3442a75ed4dd47e64e4522da625701049d64770x166ab367e077e65f1a4f273f05d8c25a3c3ea398SeasonFacet
LibWellMinting0x6dd836e7fe603bd73532bf6b5cbb188b7fcc7fa90xd76d2011647f57071cca0d182f0d524abeaee84eSeasonFacet
LibFlood0xff823fbb0ae114b8e41c0529c7d87702cc5d06a80x20a9aeac56fee169dec4d8a5c454e818b55fa8afSeasonFacet
LibGerminate0x74f0910564523a9a9a0b4db23505f653af20548c0xaedabcc13a7c44d612cb3776b6a2f3a81fd3d932SeasonFacet
LibWeatherN/A — new dependency0x82e2cfe47cf2ddd23755f81abb1349bdd96b5bfeSeasonFacet

Changed the fixed 1 Soil sellout threshold to min(50 Soil, 10% of initial Soil), and added a Mostly Sold Out threshold equal to the sold-out threshold plus 20% of the remaining initial Soil. Integer calculations round down in 6-decimal Soil units. Changed the Convert Down Penalty scaling denominator from the optimal (40%) to the lower L2SR bound (12%). Added an L2SR input cap at the lower bound, while retaining the final 100% penalty cap. The counter rate of 1 per Season and cap of 12 were unchanged.

Function Changes

Event Changes