Skip to content

Commit d934805

Browse files
committed
feat: add pricing validation with upper bounds
- Replace string literal error with Errors.AtLeastOnePriceMustBeNonZero() - Add 4x upper bounds on pricing updates (storage: 10 USDFC, cdn/cacheMiss: 2 USDFC) - Add Errors.PriceExceedsMaximum() for bound violations - Prices above bounds require contract upgrade via announcePlannedUpgrade()
1 parent 8ecb6ec commit d934805

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1212
- Added `updatePricing(uint256 newStoragePrice, uint256 newCacheMissPrice, uint256 newCdnPrice)` function to allow owner to update pricing rates without contract upgrades
1313
- Pass 0 for any parameter to keep that price unchanged (selective updates)
1414
- At least one parameter must be non-zero
15+
- Prices cannot exceed 4x their initial values (max: storage 10 USDFC, cacheMiss/cdn 2 USDFC)
1516
- New rates apply to all active data sets on their next proving period update
1617
- Added `getCurrentPricingRates()` function to query current pricing values
1718
- Added `PricingUpdated` event to track pricing changes
19+
- Added `AtLeastOnePriceMustBeNonZero` and `PriceExceedsMaximum` errors for pricing validation
1820

1921
## [0.3.0] - 2025-10-08 - M3.1 Calibration Network Deployment
2022

service_contracts/src/Errors.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,4 +286,13 @@ library Errors {
286286
/// @param dataSetId The data set ID
287287
/// @param pdpEndEpoch The end epoch when the PDP payment rail will finalize
288288
error PaymentRailsNotFinalized(uint256 dataSetId, uint256 pdpEndEpoch);
289+
290+
/// @notice At least one pricing parameter must be non-zero when updating prices
291+
error AtLeastOnePriceMustBeNonZero();
292+
293+
/// @notice Price exceeds the maximum allowed value (4x initial value)
294+
/// @param priceType Description of which price exceeded the limit
295+
/// @param maxAllowed The maximum allowed price value
296+
/// @param actual The actual price value provided
297+
error PriceExceedsMaximum(string priceType, uint256 maxAllowed, uint256 actual);
289298
}

service_contracts/src/FilecoinWarmStorageService.sol

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ contract FilecoinWarmStorageService is
198198
uint256 private immutable DEFAULT_CDN_LOCKUP_AMOUNT; // 0.7 USDFC
199199
uint256 private immutable DEFAULT_CACHE_MISS_LOCKUP_AMOUNT; // 0.3 USDFC
200200

201+
// Maximum pricing bounds (4x initial values)
202+
uint256 private immutable MAX_STORAGE_PRICE_PER_TIB_PER_MONTH; // 10 USDFC (4x 2.5)
203+
uint256 private immutable MAX_CACHE_MISS_PRICE_PER_TIB_PER_MONTH; // 2 USDFC (4x 0.5)
204+
uint256 private immutable MAX_CDN_PRICE_PER_TIB_PER_MONTH; // 2 USDFC (4x 0.5)
205+
201206
// Token decimals
202207
uint8 private immutable TOKEN_DECIMALS;
203208

@@ -331,6 +336,11 @@ contract FilecoinWarmStorageService is
331336
// Initialize the lockup constants based on the actual token decimals
332337
DEFAULT_CDN_LOCKUP_AMOUNT = (7 * 10 ** TOKEN_DECIMALS) / 10; // 0.7 USDFC
333338
DEFAULT_CACHE_MISS_LOCKUP_AMOUNT = (3 * 10 ** TOKEN_DECIMALS) / 10; // 0.3 USDFC
339+
340+
// Initialize maximum pricing bounds (4x initial values)
341+
MAX_STORAGE_PRICE_PER_TIB_PER_MONTH = (20 * 10 ** TOKEN_DECIMALS) / 2; // 10 USDFC (4x 2.5)
342+
MAX_CACHE_MISS_PRICE_PER_TIB_PER_MONTH = (4 * 10 ** TOKEN_DECIMALS) / 2; // 2 USDFC (4x 0.5)
343+
MAX_CDN_PRICE_PER_TIB_PER_MONTH = (4 * 10 ** TOKEN_DECIMALS) / 2; // 2 USDFC (4x 0.5)
334344
}
335345

336346
/**
@@ -469,23 +479,35 @@ contract FilecoinWarmStorageService is
469479
/**
470480
* @notice Updates the pricing rates for storage and CDN services
471481
* @dev Only callable by the contract owner. Pass 0 to keep existing value unchanged.
472-
* @param newStoragePrice New storage price per TiB per month (0 = no change)
473-
* @param newCacheMissPrice New cache miss price per TiB per month (0 = no change)
474-
* @param newCdnPrice New CDN price per TiB per month (0 = no change)
482+
* Prices cannot exceed 4x their initial values without a contract upgrade.
483+
* @param newStoragePrice New storage price per TiB per month (0 = no change, max 10 USDFC)
484+
* @param newCacheMissPrice New cache miss price per TiB per month (0 = no change, max 2 USDFC)
485+
* @param newCdnPrice New CDN price per TiB per month (0 = no change, max 2 USDFC)
475486
*/
476487
function updatePricing(uint256 newStoragePrice, uint256 newCacheMissPrice, uint256 newCdnPrice)
477488
external
478489
onlyOwner
479490
{
480-
require(newStoragePrice > 0 || newCacheMissPrice > 0 || newCdnPrice > 0, "At least one price must be non-zero");
491+
if (newStoragePrice == 0 && newCacheMissPrice == 0 && newCdnPrice == 0) {
492+
revert Errors.AtLeastOnePriceMustBeNonZero();
493+
}
481494

482495
if (newStoragePrice > 0) {
496+
if (newStoragePrice > MAX_STORAGE_PRICE_PER_TIB_PER_MONTH) {
497+
revert Errors.PriceExceedsMaximum("storage", MAX_STORAGE_PRICE_PER_TIB_PER_MONTH, newStoragePrice);
498+
}
483499
storagePricePerTibPerMonth = newStoragePrice;
484500
}
485501
if (newCacheMissPrice > 0) {
502+
if (newCacheMissPrice > MAX_CACHE_MISS_PRICE_PER_TIB_PER_MONTH) {
503+
revert Errors.PriceExceedsMaximum("cacheMiss", MAX_CACHE_MISS_PRICE_PER_TIB_PER_MONTH, newCacheMissPrice);
504+
}
486505
cacheMissPricePerTibPerMonth = newCacheMissPrice;
487506
}
488507
if (newCdnPrice > 0) {
508+
if (newCdnPrice > MAX_CDN_PRICE_PER_TIB_PER_MONTH) {
509+
revert Errors.PriceExceedsMaximum("cdn", MAX_CDN_PRICE_PER_TIB_PER_MONTH, newCdnPrice);
510+
}
489511
cdnPricePerTibPerMonth = newCdnPrice;
490512
}
491513

0 commit comments

Comments
 (0)