fix: allow abandonment and consensual termination of underfunded data sets - #520
Conversation
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
…geRates Assisted-by: Claude:claude-sonnet-4-6
…ndonRails and updateStorageRates Assisted-by: Claude:claude-sonnet-4-6
There was a problem hiding this comment.
Pull request overview
This PR updates the warm-storage payment-rail teardown flow so that consensual termination and abandonment can proceed even when a payer is underfunded and FilecoinPay rejects attempts to reduce the lockup period to zero.
Changes:
- Update
Rails.abandonRailsandRails.updateStorageRatesto toleratemodifyRailLockupreverts when attemptinglockupPeriod = 0, while still releasing the fixed (lifecycle reserve) portion. - Add tests covering abandonment and consent-termination behavior for underfunded payers.
- Update spec and changelog to document the underfunded-payer termination semantics.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
SPEC.md |
Documents how immediate termination/abandonment behave for well-funded vs underfunded payers. |
service_contracts/test/Abandonment.t.sol |
Adds test coverage and helpers for underfunded payer scenarios. |
service_contracts/src/lib/Rails.sol |
Adds try/catch handling around lockup-period zeroing for abandonment and immediate termination paths. |
CHANGELOG.md |
Notes the fix for underfunded payer handling in abandonment / immediate-termination rate updates. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…termination Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-sonnet-4-6
| **CDN rails are not checked**: The settled-up-to requirement above and the `pdpEndEpoch` checks in the timing list both apply to the PDP rail only. FWSS does not verify CDN rail termination or settlement before allowing dataset deletion, because it does not track the CDN rails' `endEpoch` (there is no validator callback to set it). In the normal flow this is safe: CDN rails are terminated as part of the `dataSetDeleted` callback itself. | ||
|
|
||
| **Abandonment path**: When `pdpEndEpoch == 0` (the SP never called `terminateService`), the data set can still be deleted once inactive for `INACTIVITY_WINDOW` (30 days from `lastProvenEpoch`, or from `provingActivationEpoch` for activated-but-never-proven data sets). PDPVerifier gates this: SP-only within the window, permissionless after. FWSS layers its own `_verifyInactivity` check on top so the SP cannot use this path to skip `terminateService` on an active data set. Inline teardown via `Rails.abandonRails` settles the PDP rail (advancing through unproven epochs via the pre-activation short-circuit), releases the lifecycle reserve and streaming buffer back to the payer, terminates and finalises the rail, and best-efforts the CDN rails. The SP forfeits any pending one-time op-fees; this is intentional, since the SP walked away. | ||
| **Abandonment path**: When `pdpEndEpoch == 0` (the SP never called `terminateService`), the data set can still be deleted once inactive for `INACTIVITY_WINDOW` (30 days from `lastProvenEpoch`, or from `provingActivationEpoch` for activated-but-never-proven data sets). PDPVerifier gates this: SP-only within the window, permissionless after. FWSS layers its own `_verifyInactivity` check on top so the SP cannot use this path to skip `terminateService` on an active data set. Inline teardown via `Rails.abandonRails` settles the PDP rail (advancing through unproven epochs via the pre-activation short-circuit), releases the lifecycle reserve back to the payer, terminates the rail, and best-efforts the CDN rails. The SP forfeits any pending one-time op-fees; this is intentional, since the SP walked away. For well-funded payers the lockup period is zeroed before termination, releasing the streaming buffer immediately. For underfunded payers the lockup period cannot be zeroed, so the PDP rail retains its default 30-day window and the streaming buffer is released only after that window elapses. |
There was a problem hiding this comment.
could add an extension to this para about how it works now
rvagg
left a comment
There was a problem hiding this comment.
nice; couple of doc nits, but that CHANGELOG correction needs to be taken care of - don't edit the 1.3.0 section, make a new Unreleased section
Assisted-by: Claude:claude-sonnet-4-6
|
Is there anything blocking merging this? |
|
@rjan90 : I think we incorporate Rod's doc nits and then merge. |
Co-authored-by: Rod Vagg <rod@vagg.org>
Two build fixes from rebasing onto main: abandonRails (underfunded-payer handling, FilOzone#520) uses DEFAULT_LOCKUP_PERIOD, which this branch moved from PriceListUSDFC to PriceList — import it from its new home; and the new announce-upgrade-only-owner test constructs FWSS, which now takes the optional USDC token parameter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reviewer @rvagg
Fixes #519
Consensual termination and abandonment both attempt to set the endEpoch to block.number in order to allow immediate cleanup.
Because we cannot modify the payment rate or the lockup for underfunded data sets before termination (see FilOzone/filecoin-pay#290), we are unable to reduce the lockup period to ensure endEpoch is the current block.
Instead of reverting, we will release the fixed lockup after termination.
Changes