PI-14: wstETH Liquidity, Pod Referrals and Batched Operations
Executed on January 20, 2026 at 01:14 UTC.
Summary
- wstETH Liquidity: Whitelist the Pinto-wstETH Well to decentralize the assets providing liquidity against Pinto.
- Dynamic LP Distribution: Add a dynamic LP Distribution Gauge to shift the optimal Deposited LP distribution from Pinto-cbETH to Pinto-wstETH over 360 successful scheduled updates.
- Pod Referrals: Introduce Pod referrals to reward eligible Farmers for attracting Sowing, and adjust above-peg Soil issuance for the additional Pods.
- Tractor Dynamic Data: Add dynamic operator data and compressed-data publication to Tractor.
- Batch Converts: Add batch Converts, including multiple Anti-Lambda-Lambda Converts, to reduce repeated transaction overhead.
- Batch Pod Marketplace Operations: Add batch creation, filling and cancellation of Pod Listings and Pod Orders.
Links
- Implementation PR: PR #164
- Implementation Commit: 2fcb63cc421b22c766c92e7d10115217baa9bf98
- Diamond Cut Transaction: 0x7db9dd06d7f805663da3cedcae5b4201f7db5f57e36fc5f354d9c50f7cc8a93e
Problems
1. wstETH Liquidity
Pinto exclusively incentivized liquidity that was issues by Coinbase/Circle. Concentrated exposure to a single (set) of entities goes directly against Pinto’s value proposition as a censorship resistant currency.
2. Dynamic LP Distribution
Optimal LP distribution targets were fixed until updated. Prior to this upgrade changes in distribution targets happened all at once, not gradually over time.
3. Pod Referrals
Farmers did not receive a protocol referral bonus for attracting another Farmer to Sow.
4. Tractor Dynamic Data
Tractor’s existing operator paste instructions filled specified locations in signed Blueprint calldata. They did not provide a separate key-value channel through which Blueprint contracts could read arbitrary-length operator data during execution. Publishing a Requisition also required emitting its full structured data.
5. Batch Converts
Multiple Convert operations required separate calls, including repeated checks around each call. Each Anti-Lambda-Lambda Convert could update only one Deposit, so updating several Deposits required several operations even when bundled through farm or advancedFarm.
6. Batch Pod Marketplace Operations
Creating, filling or cancelling several Pod Listings or Pod Orders required individual calls. Combining calls through farm or advancedFarm still repeated the checks around each marketplace action.
Solutions
1. wstETH Liquidity
Deploy and whitelist an upgradeable Constant Product 2 Pinto-wstETH Well. wstETH is the non-rebasing wrapped representation of Lido’s stETH. Its value reflects the underlying staking position rather than an automatically increasing token balance. The Base deployment introduces a different staking-provider exposure alongside Pinto’s existing assets.
Configure the Well with the Multi Flow Pump, the existing default Gauge Point and liquidity-weight implementations, and a composed Chainlink oracle using ETH/USD and wstETH/ETH feeds. Start its optimal Deposited LP share and Gauge Points at zero, with an initial Stalk growth rate of 1 raw unit per PDV per Season.
2. Dynamic LP Distribution
Add a stateful LP Distribution Gauge with two configured entries. Decrease Pinto-cbETH’s optimal share from 33.333333% to 0% and increase Pinto-wstETH’s share from 0% to 33.333333%. Each scheduled update changes the two targets by 0.092593 percentage points in opposite directions, clamping the final step to the target. Starting from these values, the targets are reached on update 360. A subsequent successful update disables the Gauge after finding both targets already reached.
During Sunrise, the existing Seed Gauge runs before the generalized Gauges. The new optimal shares therefore affect subsequent Seed Gauge calculations. Changing these targets adjusts incentives. It does not transfer liquidity or move Farmers’ Deposits automatically.
Each distribution entry can optionally supply a function that recalculates its signed change. Neither initial entry configures such a function. A failed optional call or unsupported encoding retains that entry’s prior change. A failed outer Gauge call retains its stored value and data and rolls back changes made within that call. If a Gauge call succeeds but returns incorrectly encoded data, decoding that data reverts the entire Sunrise transaction.
The 360-update progression describes the configured Sunrise path. The deployed lpDistributionUpdateGauge entry point also accepts caller-supplied Gauge data without an owner-only or self-call restriction. The implementation therefore does not enforce an exclusive once-per-Season schedule for all calls to that entry point.
3. Pod Referrals
Add sowWithReferral, allowing a Farmer to specify a referrer while retaining sowWithMin’s minimum acceptable Temperature, minimum Soil requirement and choice of balance source. An eligible, nonzero referrer distinct from the Sowing Farmer receives a nominal 10% bonus, and the referred Farmer receives a nominal 5% bonus. These rates apply to rounded portions of the Pinto actually Sown and are converted into Pods using the same Sowing calculation.
Issue the ordinary Plot first, then the referred Farmer’s bonus Plot, then the referrer’s bonus Plot. Bonus Pods consume no additional Soil and burn no additional Pinto. Both bonus allocations count toward one protocol-wide limit of 2,000,000 Pods. When approaching the limit, the referred Farmer’s bonus is allocated first, and the referrer receives only the remaining budget. Referral bonuses stop when the shared limit is reached. Invalid referrals leave ordinary Sowing intact with zero referral bonuses.
Track Pinto Sown for referral eligibility. A Farmer qualifies after Sowing at least 1,000 Pinto, including the historical values loaded at initialization. An eligible Farmer who meets this Sowing threshold can designate an otherwise ineligible address as a delegate, change that delegate, or clear it. This grants eligibility to the specified address. Bonuses are paid to the eligible address passed as the referral, rather than automatically redirected from the original Farmer’s address.
Adjust the above-peg Soil calculation by multiplying its Temperature-based debt denominator by 1 + referrerPercentage + refereePercentage, with the percentages normalized to their six-decimal representation. At the initialized rates this factor is 1.15 before the existing Pod Rate and cultivation adjustments. The implemented formula uses the configured percentages even when no valid referral is used or the bonus budget has been exhausted. It does not check isReferralSystemEnabled(). Below-peg Soil issuance is not changed by this formula. The configured percentages continue to reduce calculated Soil after the cap is exhausted until a subsequent change alters the implementation or parameters.
4. Tractor Dynamic Data
Add tractorDynamicData, which accepts the existing signed Requisition and static operator data plus an array of numeric keys and arbitrary byte values. Blueprint contracts can read these values through getTractorData(key) during execution. The function clears the supplied keys after the Tractor calls complete, and transient storage is also cleared at transaction end. Missing or cleared keys return empty bytes.
Preserve Requisition verification, Blueprint execution limits and the existing execution-result array. Add publishData(bytes), which emits the supplied bytes for off-chain distribution. It does not decompress the data or verify a Requisition. Keep publishRequisition as the separate verified structured-publication path.
5. Batch Converts
Add batchConvert, which processes a nonempty array of Convert requests in order using shared Convert logic. Each request supplies its encoded Convert type, Deposit stems, token counts and signed Grown Stalk slippage tolerance. The result array returns the Convert kind, resulting Stem, input and output token counts, and input and output PDV for each operation (the ABI retains the fromBdv and toBdv field names).
Each Anti-Lambda-Lambda item still updates only one Deposit. Several such items can appear in one batch. Each operation sees the state left by earlier operations, including consumed Convert capacity. If any operation or the enclosing checks revert, the entire batch reverts.
6. Batch Pod Marketplace Operations
Add batch functions to create, fill and cancel Pod Listings and Pod Orders. Preserve the existing ownership, listing/order validation, transfer and allowance rules through the shared helpers. Each batch runs in order and is atomic if an operation reverts.
Listing fills use one payer balance mode for the batch while preserving each Listing’s receiving mode. Order creation makes one aggregate token-receipt call for the requested Pinto and returns an array of Order IDs. Order fills and cancellations use one receiving mode per batch. The existing single-operation entry points remain available.
Rationale
1. wstETH Liquidity
Adding a Lido-based staking asset diversifies provider exposure away from Coinbase/Circle to support the protocol’s censorship-resistance objective.
2. Dynamic LP Distribution
A gradual change gives Farmers time to respond to changing Seed incentives while preserving the combined configured optimal share of the two ETH-linked Wells. The generalized mechanism eliminates the need for repeated manual target updates.
3. Pod Referrals
The referral incentive rewards attracting additional Sowing while bounding the total bonus debt. The tradeoff is more Pods for the same number of Pinto burned. The proposal favored that additional cost to attract Sowing. The eligibility threshold ties access to prior participation to create a cost for self-referrals, while delegation supports a separate referral address designed to preserve on-chain privacy.
The revised above-peg denominator accounts for full referral participation when setting Soil. When participation is lower or the bonus cap is met, realized bonus issuance can be lower than this assumption.
4. Tractor Dynamic Data
A transient key-value channel lets Blueprint contracts consume variable-length information without forcing it into fixed paste locations in signed calldata. Explicit cleanup limits the lifetime to the Tractor call on the successful path, while EIP-1153 supplies transaction-level cleanup. Compressed-data publication provides an off-chain distribution option without changing what constitutes a valid signed Requisition.
5. Batch Converts
Batch Converts apply asset-backing and Pinto-supply checks, together with reentrancy protection, once around the entire batch. Each Convert retains its own accounting, slippage enforcement and events. This reduces repeated overhead and allows multiple Deposit valuation updates in one transaction. If any Convert fails, the entire batch reverts.
6. Batch Pod Marketplace Operations
Batching reduces repeated checks and, for Order creation, repeated token receipts. It simplifies submitting several related operations while retaining individual marketplace events.
Contract Changes
Initialization
Executed InitPI14.init(address,uint256) at 0xc1d6cfc744fd017ebc989e63d89374bee1e5a1fc, passing helper storage 0xbe95c6806ab4eefc10ac9e96938c3a222964dd91 and key 1.
The initializer deployed and whitelisted the Pinto-wstETH Well, configured the stateful LP Distribution Gauge, and loaded historical referral eligibility data from the helper. Execution events confirmed the 10% referrer rate, 5% referee rate, 2,000,000-Pod budget and 1,000-Pinto eligibility threshold. The initializer did not update Tractor’s version. Historical before/after calls both returned 1.0.0.
The storage update moved s.sys.initialSoil to the upper half of its slot and used the lower half for the referral eligibility threshold. It did not migrate the previous starting-Soil value. At the execution block, getSoilSoldOutThreshold() and getSoilMostlySoldOutThreshold() returned zero, down from 20.497512 and 57.393033 Soil respectively in the preceding block. Sun.setSoil populates the relocated field at the next successful Sunrise. The public initialSoil() getter still returns remaining s.sys.soil.
Facet Changes
Replaced 228 selectors and added 22 selectors across 19 facet implementations. No selectors were removed. Add / Replace denotes facets receiving both new and existing selectors. Replacement alone does not mean every function in a facet changed.
Other Contract / Parameter Changes
Deployed the Pinto-wstETH Well proxy at 0x3e1155245ff9a6a019bc35827e801c6ed2ce91b9, with the Well implementation instance at 0x3e11afd88f9987df06557ee84d8a38879b0503b0. The Base wstETH token is 0xc1cba3fcea344f92d9239c08c0568f6f2f0ee452.
Configured the existing LSDChainlinkOracle at 0x3ca165997a12863eb63e4418d2e97aca3cdcdadc with ETH/USD feed 0x71041dddad3595f9ced3dccfbe3d1f4b0a16bb70 and a 3,600-second timeout, and wstETH/ETH feed 0x43a5c292a453a3bf3606fa856197f09d7b74251a and a 129,600-second timeout. The new asset uses wellBdv, issues 1e10 raw Stalk units per PDV, and starts with stalkEarnedPerSeason = 1, zero Gauge Points and zero optimal share.
The Well uses Aquifer 0xba51aa60b3b8d9a36cc748a62aa56801060183f8, base Well implementation 0xba510990a720725ab1f9a0d231f045fc906909f4, Constant Product 2 at 0xba510c289fd067ebba41335afa11f0591940d6fe and Multi Flow Pump at 0xba51aaaa66dab6c236b356ad713f759c206dcb93. These configured components were not new PI-14 component deployments.
The linked-library inventory below lists the external dependencies of the added or replaced facets. It also identifies LibConvert as a consumer of LibTokenSilo. LibSeedGauge is the renamed successor to LibGauge, shown in the previous-implementation column. All listed deployments changed. A changed address does not imply a changed economic rule in that library’s own source.
Function Changes
- Added the initialization path that deploys the upgradeable Well and registers its asset settings and composed price oracle. It configured the two opposite LP-target changes as described above.
- Added
lpDistributionUpdateGauge(bytes,bytes,bytes)and the internalLibGaugeLogic/LibLpDistributionGaugeupdate path. It returns an empty Gauge value and updated encoded Gauge data while writing optimal shares. Added stateful Gauge dispatch through ordinary calls alongside stateless dispatch through static calls. The public result getters remain stateless and do not apply the stateful update. RenamedLibGauge.stepGaugetoLibSeedGauge.stepSeedGaugewithout changing the Seed Gauge algorithm itself.
- Added
sowWithReferral, returning ordinary Pods, referrer bonus Pods and referee bonus Pods separately. Updated the sharedLibDibblerSowing path to track eligibility and issue capped bonuses. ExistingsowandsowWithMinstill return ordinary Pods and pass no referral.
- Added
delegateReferralRewardsand referral getters for percentages, eligibility threshold, eligibility, tracked Sowing, delegate, target, total issued and enabled status. Delegation requires the caller’s own tracked Sowing to meet the threshold and forbids self-delegation or selecting an already eligible delegate. Replacing a delegate clears the former delegate’s eligibility flag. The current delegate’s flag is cleared before the eligibility check, so reselecting the same delegate succeeds.
- Updated
Sun.setSoilAbovePegto use the referral-adjusted debt denominator. The existing Pod Rate and cultivation adjustments remain downstream. The calculation does not condition this adjustment on remaining referral budget.
- Added
tractorDynamicDataandgetTractorData. Moved the shared Tractor execution path intoLibTractor, retaining signature verification, operator pasting, per-call results, nonce handling and cleanup. Added internal transient-storage helpers for the dynamic byte values. The existing persistent Tractor storage slot and field order were retained.
- Added
publishData(bytes)as an event-only publication function. Removed the funds, net-flow, supply and reentrancy modifiers frompublishRequisitionandcancelBlueprint, while retaining Requisition verification and their existing nonce or publisher checks. This does not makepublishDataa verified Requisition publication.
- Added
ConvertBatchFacet.batchConvertand moved the existing Convert core intoConvertBase._convert, shared withConvertFacet. Retained the one-Deposit restriction per Anti-Lambda-Lambda operation, Grown Stalk slippage checks, capacity updates, PDV accounting and non-Germinating minimum logic. The batch returns an array of structured results and rejects an empty input array.
- Added
batchCreatePodListing,batchFillPodListing,batchCancelPodListing,batchCreatePodOrder,batchFillPodOrderandbatchCancelPodOrder. Only batch Order creation returns Order IDs. Unlike single Order creation, the batch records the requested quantities without adjusting them to the actual receipt returned byreceiveToken. Moved the existing Pod allowance getter intoMarketplaceFacetand shared allowance checking through_checkAndDecrementAllowance, preserving the public getter signature and the unlimited-allowance exemption.
Event Changes
- Emitted the existing Well deployment, proxy initialization and whitelist configuration events for the new asset, including
UpdateWhitelistStatus,WhitelistToken,UpdatedOracleImplementationForToken,UpdatedGaugePointImplementationForTokenandUpdatedLiquidityWeightImplementationForToken.
- Added
AddedStatefulGaugealongside the existingAddedGaugeduring LP Distribution Gauge initialization. Successful Gauge dispatch continues to emitEngagedandEngagedData, including retained results after a failed low-level Gauge call.
- Added the initialization events
ReferralPercentageChanged,RefereePercentageChanged,TargetReferralPodsChangedandBeanSownEligibilityThresholdChanged, carrying the configured integer values. Referral percentages use six-decimal precision, despite an inaccurate source comment referring to eighteen decimals.
- Added
SowReferral, identifying the referrer and referee, their bonus Plot indexes and the number of bonus Pods. The shared Sowing path also emits the existingSowevent for each issued bonus Plot with zero Pinto burned. Ordinary Sowing still emits its ownSow. An invalid referral does not emitSowReferral. Moved the Soil-demand timing check before Plot creation, soSoilMostlySoldOutorSoilSoldOut, when emitted, precedes the correspondingSow.
- Added
PublishData(bytes)to emit the submitted payload. Existing Requisition, Blueprint cancellation and Tractor execution event interfaces were retained.
- Batch Converts emit the existing per-operation
Convertevents and applicable shared accounting/bonus/penalty events. No separate aggregate batch event was added.
- Batch marketplace operations emit the existing per-item Listing, Order and Plot events through their shared helpers. No separate aggregate marketplace batch event was added.