PI-14: wstETH Liquidity, Pod Referrals and Batched Operations

Executed on January 20, 2026 at 01:14 UTC.

Summary

  1. wstETH Liquidity: Whitelist the Pinto-wstETH Well to decentralize the assets providing liquidity against Pinto.
  1. 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.
  1. Pod Referrals: Introduce Pod referrals to reward eligible Farmers for attracting Sowing, and adjust above-peg Soil issuance for the additional Pods.
  1. Tractor Dynamic Data: Add dynamic operator data and compressed-data publication to Tractor.
  1. Batch Converts: Add batch Converts, including multiple Anti-Lambda-Lambda Converts, to reduce repeated transaction overhead.
  1. Batch Pod Marketplace Operations: Add batch creation, filling and cancellation of Pod Listings and Pod Orders.

Links

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.

FacetActionPrevious ImplementationNew Implementation
GaugeFacetAdd / Replace0xa98400591c72ce2a2bde3b170f5a6a1b070ee4ea0xf9f1d9c6ef1ca5ec0897c266d7b4e016e955d916
GaugeGettersFacetReplace0x7d5b807202b8ae3dfb4b6d988d85622590b228620xc0b381741820808b6407cdc8b03e8561259f8e5d
SeasonFacetReplace0xb9d1c6e65a8934ec86d70f358028943e63ee07930x4aeee50b11c3682605dceca1feacd96349383cd2
FieldFacetAdd / Replace0x32124b4da9b23659c1ad4b8be4fc2d274701c3d10xae94197e16b31443fe1c333a32eda30eb3c1a942
TractorFacetAdd / Replace0xc2fc7963f76205dc57842e1a90c3e487bd16a5560xc8706ff2a0da6b3367aa506dcbb608ccf96148de
MarketplaceFacetReplace0x5aeb7c0a256b167bae026056d32818539b1734b40x85436279a52537ef03864e268d73d3ba37e169ec
MarketplaceBatchFacetAddNot applicable — new facet0x40e42f3d568faf47c539a7d2a61e24629819bad4
ConvertFacetReplace0x508900b00970af419c915c921ecc81d7e0a7ebcb0xdc37f26363b305affc93c564ee879a265bcbff4d
ConvertGettersFacetReplace0x32a036190967a11280ecd944d90b85d86f43e24f0x334a110ad41fd417d4c8c3f82d9c85a3850192be
ConvertBatchFacetAddNot applicable — new facet0x923a7096f7338660e60b4dc0ae21d2413e399739
ClaimFacetReplace0x5e71bf027203bcbc9b1bd22504720d8e8be30cf70xfc4499f812014bebaf9686ce0312a77cca65137a
PipelineConvertFacetReplace0x51b9fca1c4900584861efc794458dfa47775dd4b0xa66460626d1f8845085b1cdd5e527db1db998b1b
SiloFacetReplace0xf4e60ecdc7ddd4037f1b9aa7d27a30d367871ca50x8646649c0f80db8665358f4548ae0d1ecc3910a5
SiloGettersFacetReplace0xa9f983f26828a99146f7f119a358ad930edbf4200x92a2ddc9d6bcde63fb4473033ef8beea4145d0fd
MetadataFacetReplace0xf6506176a027ed4d5cdbab23d9dfcdec2b35b2a80xced0ea96c44341343c13dc671c22e858e21675e0
ApprovalFacetReplace0xa456002541ffdd0cf4c8cdd273210581f2bf03140x596050ccbbe49966a29be8663b2ed6a1f5dc1870
TokenFacetReplace0x7f492edcd56335b2d2aee29dfe39df33bbe43bb80xd29e38e4a803feac3503fd7402181bba79d3d3f0
TokenSupportFacetReplace0x9d214daf535396d515d93831fc7fe5fa137b4f300x7f1bb9f51c636012cfaadc9e2db124edd21a7b92
FarmFacetReplace0x39322b0448a7c7b6abf980d204fa0c45df1886dc0x16d28e43e43c6d5b2e95140f2f3000dcf87eb1d9

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.

LibraryPrevious ImplementationNew ImplementationUsed By
LibEvaluate0xbff46c34d49b976d9c133fafb0529cff6704138b0x1105414b01a6d2214d1c33a1f756dea2e5e87259SeasonFacet
LibFlood0x3bd60d6c0df87fdd90c510d1de5c1a089f4e6b250xef75cae236476bfedc5207d57e5ea7ea315a8c12SeasonFacet
LibGerminate0xbcf22afbbda11ac84ea001451d8ae60b424b0b970x752f502897667c6ba438d35b39439c84210dad06SeasonFacet
LibIncentive0x31046cd4b22c6af8a677f641f4d706ccce1ca5700x735aab105c222bee6aaf520adc4cf3128fdcc6dbSeasonFacet
LibSeedGauge (formerly LibGauge)0x35a71bc019539dda1e04e549609c6f620644e2c70xbcc581f0d70a033e21b31ea695fd3c2978503146SeasonFacet
LibShipping0x71a9f8e8a9082381ba7352d5b82e5e0849c6ddf20xf528edef6598d1907eef6e7ad1a8b87e54c736a9SeasonFacet
LibWeather0xed46c5936939d4ffd25284b4825e14f02e4bb90d0xf8569d0f4aa794ea4c9ca5efadda38433ad52bbbSeasonFacet
LibWellMinting0x7cbd0b120a1ee1cdac1ed245ee23a80b37c7a6f90xcfceea3eeaeccb8dcda9cbc37d72523c10855c62SeasonFacet
LibConvert0xb3626b534ff81442579913de1f31c51a045b52610x7665b799e4e05c2ddc4306826322e9d0729965f7ConvertBatchFacet, ConvertFacet, PipelineConvertFacet
LibPipelineConvert0xfc537aa415b89def06d97e23c04baf4039e8bbcb0x249be8f283471f2d4f08a4dae1108c632c650d6bConvertBatchFacet, ConvertFacet, PipelineConvertFacet
LibSilo0x9f327f1f6810aaf5a4ab0704b62b4ed6bb0ea3340x648a2ab1358bf9df357772e2fd5d4ceec824ecfaClaimFacet, ConvertBatchFacet, ConvertFacet, PipelineConvertFacet, SiloFacet
LibTokenSilo0xe97ee5afcb656126c6a89b72d8617061213f9f4d0xff684446076ebc98cb2998a219dac957eb66b0aeClaimFacet, LibConvert, SiloFacet

Function Changes

Event Changes