@@ -97,6 +97,8 @@ contract FilecoinWarmStorageService is
9797 event ProviderApproved (uint256 indexed providerId );
9898 event ProviderUnapproved (uint256 indexed providerId );
9999
100+ event PricingUpdated (uint256 storagePrice , uint256 minimumRate );
101+
100102 // =========================================================================
101103 // Structs
102104
@@ -193,16 +195,18 @@ contract FilecoinWarmStorageService is
193195 bytes32 private constant WITH_CDN_STRING_STORAGE_REPR =
194196 0x7769746843444e0000000000000000000000000000000000000000000000000e ;
195197
196- // Pricing constants
197- uint256 private immutable STORAGE_PRICE_PER_TIB_PER_MONTH; // 2.5 USDFC per TiB per month without CDN with correct decimals
198+ // Pricing constants (CDN egress pricing is immutable)
198199 uint256 private immutable CDN_EGRESS_PRICE_PER_TIB; // 7 USDFC per TiB of CDN egress
199200 uint256 private immutable CACHE_MISS_EGRESS_PRICE_PER_TIB; // 7 USDFC per TiB of cache miss egress
200- uint256 private immutable MINIMUM_STORAGE_RATE_PER_MONTH; // 0.06 USDFC per month minimum pricing floor
201201
202202 // Fixed lockup amounts for CDN rails
203203 uint256 private immutable DEFAULT_CDN_LOCKUP_AMOUNT; // 0.7 USDFC
204204 uint256 private immutable DEFAULT_CACHE_MISS_LOCKUP_AMOUNT; // 0.3 USDFC
205205
206+ // Maximum pricing bounds (4x initial values)
207+ uint256 private immutable MAX_STORAGE_PRICE_PER_TIB_PER_MONTH; // 10 USDFC (4x 2.5)
208+ uint256 private immutable MAX_MINIMUM_STORAGE_RATE_PER_MONTH; // 0.24 USDFC (4x 0.06)
209+
206210 // Token decimals
207211 uint8 private immutable TOKEN_DECIMALS;
208212
@@ -272,6 +276,10 @@ contract FilecoinWarmStorageService is
272276
273277 PlannedUpgrade private nextUpgrade;
274278
279+ // Pricing rates (mutable for future adjustments)
280+ uint256 private storagePricePerTibPerMonth;
281+ uint256 private minimumStorageRatePerMonth;
282+
275283 event UpgradeAnnounced (PlannedUpgrade plannedUpgrade );
276284
277285 // =========================================================================
@@ -328,11 +336,13 @@ contract FilecoinWarmStorageService is
328336 // Read token decimals from the USDFC token contract
329337 TOKEN_DECIMALS = _usdfc.decimals ();
330338
331- // Initialize the fee constants based on the actual token decimals
332- STORAGE_PRICE_PER_TIB_PER_MONTH = (5 * 10 ** TOKEN_DECIMALS) / 2 ; // 2.5 USDFC
339+ // Initialize the immutable pricing constants based on the actual token decimals
333340 CDN_EGRESS_PRICE_PER_TIB = 7 * 10 ** TOKEN_DECIMALS; // 7 USDFC per TiB
334341 CACHE_MISS_EGRESS_PRICE_PER_TIB = 7 * 10 ** TOKEN_DECIMALS; // 7 USDFC per TiB
335- MINIMUM_STORAGE_RATE_PER_MONTH = (6 * 10 ** TOKEN_DECIMALS) / 100 ; // 0.06 USDFC minimum
342+
343+ // Initialize maximum pricing bounds (4x initial values)
344+ MAX_STORAGE_PRICE_PER_TIB_PER_MONTH = 10 * 10 ** TOKEN_DECIMALS; // 10 USDFC (4x 2.5)
345+ MAX_MINIMUM_STORAGE_RATE_PER_MONTH = (24 * 10 ** TOKEN_DECIMALS) / 100 ; // 0.24 USDFC (4x 0.06)
336346
337347 // Initialize the lockup constants based on the actual token decimals
338348 DEFAULT_CDN_LOCKUP_AMOUNT = (7 * 10 ** TOKEN_DECIMALS) / 10 ; // 0.7 USDFC
@@ -383,6 +393,10 @@ contract FilecoinWarmStorageService is
383393
384394 // Set commission rate
385395 serviceCommissionBps = 0 ; // 0%
396+
397+ // Initialize mutable pricing variables
398+ storagePricePerTibPerMonth = (5 * 10 ** TOKEN_DECIMALS) / 2 ; // 2.5 USDFC
399+ minimumStorageRatePerMonth = (6 * 10 ** TOKEN_DECIMALS) / 100 ; // 0.06 USDFC
386400 }
387401
388402 function announcePlannedUpgrade (PlannedUpgrade calldata plannedUpgrade ) external onlyOwner {
@@ -467,6 +481,39 @@ contract FilecoinWarmStorageService is
467481 serviceCommissionBps = newCommissionBps;
468482 }
469483
484+ /**
485+ * @notice Updates the pricing rates for storage services
486+ * @dev Only callable by the contract owner. Pass 0 to keep existing value unchanged.
487+ * Price updates apply immediately to existing payment rails when they're recalculated
488+ * (e.g., during piece additions/deletions or proving period updates).
489+ * Maximum allowed values: 10 USDFC for storage, 0.24 USDFC for minimum rate.
490+ * @param newStoragePrice New storage price per TiB per month (0 = no change, max 10 USDFC)
491+ * @param newMinimumRate New minimum monthly storage rate (0 = no change, max 0.24 USDFC)
492+ */
493+ function updatePricing (uint256 newStoragePrice , uint256 newMinimumRate )
494+ external
495+ onlyOwner
496+ {
497+ if (newStoragePrice == 0 && newMinimumRate == 0 ) {
498+ revert Errors.AtLeastOnePriceMustBeNonZero ();
499+ }
500+
501+ if (newStoragePrice > 0 ) {
502+ if (newStoragePrice > MAX_STORAGE_PRICE_PER_TIB_PER_MONTH) {
503+ revert Errors.PriceExceedsMaximum ("storage " , MAX_STORAGE_PRICE_PER_TIB_PER_MONTH, newStoragePrice);
504+ }
505+ storagePricePerTibPerMonth = newStoragePrice;
506+ }
507+ if (newMinimumRate > 0 ) {
508+ if (newMinimumRate > MAX_MINIMUM_STORAGE_RATE_PER_MONTH) {
509+ revert Errors.PriceExceedsMaximum ("minimumRate " , MAX_MINIMUM_STORAGE_RATE_PER_MONTH, newMinimumRate);
510+ }
511+ minimumStorageRatePerMonth = newMinimumRate;
512+ }
513+
514+ emit PricingUpdated (storagePricePerTibPerMonth, minimumStorageRatePerMonth);
515+ }
516+
470517 /**
471518 * @notice Adds a provider ID to the approved list
472519 * @dev Only callable by the contract owner. Reverts if already approved.
@@ -1097,7 +1144,7 @@ contract FilecoinWarmStorageService is
10971144 /// @param payer The address of the payer
10981145 function validatePayerOperatorApprovalAndFunds (FilecoinPayV1 payments , address payer ) internal view {
10991146 // Calculate required lockup for minimum pricing
1100- uint256 minimumLockupRequired = (MINIMUM_STORAGE_RATE_PER_MONTH * DEFAULT_LOCKUP_PERIOD) / EPOCHS_PER_MONTH;
1147+ uint256 minimumLockupRequired = (minimumStorageRatePerMonth * DEFAULT_LOCKUP_PERIOD) / EPOCHS_PER_MONTH;
11011148
11021149 // Check that payer has sufficient available funds
11031150 (,, uint256 availableFunds ,) = payments.getAccountInfoIfSettled (usdfcTokenAddress, payer);
@@ -1120,7 +1167,7 @@ contract FilecoinWarmStorageService is
11201167 require (isApproved, Errors.OperatorNotApproved (payer, address (this )));
11211168
11221169 // Calculate minimum rate per epoch
1123- uint256 minimumRatePerEpoch = MINIMUM_STORAGE_RATE_PER_MONTH / EPOCHS_PER_MONTH;
1170+ uint256 minimumRatePerEpoch = minimumStorageRatePerMonth / EPOCHS_PER_MONTH;
11241171
11251172 // Verify rate allowance is sufficient
11261173 require (
@@ -1241,10 +1288,10 @@ contract FilecoinWarmStorageService is
12411288 */
12421289 function _calculateStorageRate (uint256 totalBytes ) internal view returns (uint256 ) {
12431290 // Calculate natural size-based rate
1244- uint256 naturalRate = calculateStorageSizeBasedRatePerEpoch (totalBytes, STORAGE_PRICE_PER_TIB_PER_MONTH );
1291+ uint256 naturalRate = calculateStorageSizeBasedRatePerEpoch (totalBytes, storagePricePerTibPerMonth );
12451292
12461293 // Calculate minimum rate (floor price converted to per-epoch)
1247- uint256 minimumRate = MINIMUM_STORAGE_RATE_PER_MONTH / EPOCHS_PER_MONTH;
1294+ uint256 minimumRate = minimumStorageRatePerMonth / EPOCHS_PER_MONTH;
12481295
12491296 // Return whichever is higher: natural rate or minimum rate
12501297 return naturalRate > minimumRate ? naturalRate : minimumRate;
@@ -1341,22 +1388,35 @@ contract FilecoinWarmStorageService is
13411388 */
13421389 function getServicePrice () external view returns (ServicePricing memory pricing ) {
13431390 pricing = ServicePricing ({
1344- pricePerTiBPerMonthNoCDN: STORAGE_PRICE_PER_TIB_PER_MONTH ,
1391+ pricePerTiBPerMonthNoCDN: storagePricePerTibPerMonth ,
13451392 pricePerTiBCdnEgress: CDN_EGRESS_PRICE_PER_TIB,
13461393 pricePerTiBCacheMissEgress: CACHE_MISS_EGRESS_PRICE_PER_TIB,
13471394 tokenAddress: usdfcTokenAddress,
13481395 epochsPerMonth: EPOCHS_PER_MONTH,
1349- minimumPricePerMonth: MINIMUM_STORAGE_RATE_PER_MONTH
1396+ minimumPricePerMonth: minimumStorageRatePerMonth
13501397 });
13511398 }
13521399
1400+ /**
1401+ * @notice Get the current pricing rates
1402+ * @return storagePrice Current storage price per TiB per month
1403+ * @return minimumRate Current minimum monthly storage rate
1404+ */
1405+ function getCurrentPricingRates ()
1406+ external
1407+ view
1408+ returns (uint256 storagePrice , uint256 minimumRate )
1409+ {
1410+ return (storagePricePerTibPerMonth, minimumStorageRatePerMonth);
1411+ }
1412+
13531413 /**
13541414 * @notice Get the effective rates after commission for both service types
13551415 * @return serviceFee Service fee (per TiB per month)
13561416 * @return spPayment SP payment (per TiB per month)
13571417 */
13581418 function getEffectiveRates () external view returns (uint256 serviceFee , uint256 spPayment ) {
1359- uint256 total = STORAGE_PRICE_PER_TIB_PER_MONTH ;
1419+ uint256 total = storagePricePerTibPerMonth ;
13601420
13611421 serviceFee = (total * serviceCommissionBps) / COMMISSION_MAX_BPS;
13621422 spPayment = total - serviceFee;
0 commit comments