@@ -557,13 +557,13 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
557557            mockUSDFC,
558558            address (pdpServiceWithPayments),
559559            true , // approved 
560-             1000e6 , // rate allowance (1000 USDFC) 
561-             1000e6 , // lockup allowance (1000 USDFC) 
560+             1000e18 , // rate allowance (1000 USDFC) 
561+             1000e18 , // lockup allowance (1000 USDFC) 
562562            365  days  // max lockup period 
563563        );
564564
565565        // Client deposits funds to the FilecoinPayV1 contract for future payments 
566-         uint256  depositAmount =  10e6 ; // Sufficient funds for initial lockup and future operations 
566+         uint256  depositAmount =  10e18 ; // Sufficient funds for initial lockup and future operations 
567567        mockUSDFC.approve (address (payments), depositAmount);
568568        payments.deposit (mockUSDFC, client, depositAmount);
569569        vm.stopPrank ();
@@ -682,13 +682,13 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
682682            mockUSDFC,
683683            address (pdpServiceWithPayments),
684684            true , // approved 
685-             1000e6 , // rate allowance (1000 USDFC) 
686-             1000e6 , // lockup allowance (1000 USDFC) 
685+             1000e18 , // rate allowance (1000 USDFC) 
686+             1000e18 , // lockup allowance (1000 USDFC) 
687687            365  days  // max lockup period 
688688        );
689689
690690        // Client deposits funds to the FilecoinPayV1 contract for future payments 
691-         uint256  depositAmount =  10e6 ; // Sufficient funds for initial lockup and future operations 
691+         uint256  depositAmount =  10e18 ; // Sufficient funds for initial lockup and future operations 
692692        mockUSDFC.approve (address (payments), depositAmount);
693693        payments.deposit (mockUSDFC, client, depositAmount);
694694        vm.stopPrank ();
@@ -795,11 +795,11 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
795795            mockUSDFC,
796796            address (pdpServiceWithPayments),
797797            true , // approved 
798-             1000e6 , // rate allowance (1000 USDFC) 
799-             1000e6 , // lockup allowance (1000 USDFC) 
798+             1000e18 , // rate allowance (1000 USDFC) 
799+             1000e18 , // lockup allowance (1000 USDFC) 
800800            365  days  // max lockup period 
801801        );
802-         uint256  depositAmount =  10e6 ; // Sufficient funds for initial lockup and future operations 
802+         uint256  depositAmount =  10e18 ; // Sufficient funds for initial lockup and future operations 
803803        mockUSDFC.approve (address (payments), depositAmount);
804804        payments.deposit (mockUSDFC, client, depositAmount);
805805        vm.stopPrank ();
@@ -909,38 +909,149 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
909909        // Test the values returned by getServicePrice 
910910        FilecoinWarmStorageService.ServicePricing memory  pricing =  pdpServiceWithPayments.getServicePrice ();
911911
912-         uint256  decimals =  6 ; // MockUSDFC uses 6  decimals in tests 
913-         uint256  expectedNoCDN =  25  *  10  **  (decimals -  1 ); // 2.5 USDFC with 6  decimals 
914-         uint256  expectedWithCDN =  3  *  10  **  decimals; // 3 USDFC with 6  decimals (2.5 + 0.5 CDN) 
912+         uint256  decimals =  18 ; // MockUSDFC uses 18  decimals in tests 
913+         uint256  expectedNoCDN =  25  *  10  **  (decimals -  1 ); // 2.5 USDFC with 18  decimals 
914+         uint256  expectedWithCDN =  3  *  10  **  decimals; // 3 USDFC with 18  decimals (2.5 + 0.5 CDN) 
915915
916916        assertEq (pricing.pricePerTiBPerMonthNoCDN, expectedNoCDN, "No CDN price should be 2.5 * 10^decimals " );
917917        assertEq (pricing.pricePerTiBPerMonthWithCDN, expectedWithCDN, "With CDN price should be 3 * 10^decimals " );
918918        assertEq (address (pricing.tokenAddress), address (mockUSDFC), "Token address should match USDFC " );
919919        assertEq (pricing.epochsPerMonth, 86400 , "Epochs per month should be 86400 " );
920920
921921        // Verify the values are in expected range 
922-         assert (pricing.pricePerTiBPerMonthNoCDN <  10  **  8 ); // Less than 10^8  
923-         assert (pricing.pricePerTiBPerMonthWithCDN <  10  **  8 ); // Less than 10^8  
922+         assert (pricing.pricePerTiBPerMonthNoCDN <  10  **  20 ); // Less than 10^20  
923+         assert (pricing.pricePerTiBPerMonthWithCDN <  10  **  20 ); // Less than 10^20  
924924    }
925925
926926    function testGetEffectiveRatesValues  () public  view  {
927927        // Test the values returned by getEffectiveRates 
928928        (uint256  serviceFee , uint256  spPayment ) =  pdpServiceWithPayments.getEffectiveRates ();
929929
930-         uint256  decimals =  6 ; // MockUSDFC uses 6  decimals in tests 
931-         // Total is 2.5 USDFC with 6  decimals 
930+         uint256  decimals =  18 ; // MockUSDFC uses 18  decimals in tests 
931+         // Total is 2.5 USDFC with 18  decimals 
932932        uint256  expectedTotal =  25  *  10  **  (decimals -  1 );
933933
934934        // Test setup uses 0% commission 
935935        uint256  expectedServiceFee =  0 ; // 0% commission 
936936        uint256  expectedSpPayment =  expectedTotal; // 100% goes to SP 
937937
938938        assertEq (serviceFee, expectedServiceFee, "Service fee should be 0 with 0% commission " );
939-         assertEq (spPayment, expectedSpPayment, "SP payment should be 2.5 * 10^6  " );
940-         assertEq (serviceFee +  spPayment, expectedTotal, "Total should equal 2.5 * 10^6  " );
939+         assertEq (spPayment, expectedSpPayment, "SP payment should be 2.5 * 10^18  " );
940+         assertEq (serviceFee +  spPayment, expectedTotal, "Total should equal 2.5 * 10^18  " );
941941
942942        // Verify the values are in expected range 
943-         assert (serviceFee +  spPayment <  10  **  8 ); // Less than 10^8 
943+         assert (serviceFee +  spPayment <  10  **  20 ); // Less than 10^20 
944+     }
945+ 
946+     // Minimum Pricing Tests 
947+     function testMinimumPricing_SmallDataSetsPayFloorRate  () public  view  {
948+         // Small datasets should all pay the minimum floor rate of 0.06 USDFC/month 
949+         uint256  decimals =  18 ;
950+         uint256  oneGiB =  1024  *  1024  *  1024 ;
951+ 
952+         // Expected minimum: 0.06 USDFC/month = 6/100 with 18 decimals 
953+         uint256  expectedMinPerMonth =  (6  *  10  **  decimals) /  100 ;
954+         uint256  expectedMinPerEpoch =  expectedMinPerMonth /  86400 ; // Convert to per-epoch 
955+ 
956+         // Test 0 bytes 
957+         (uint256  rateZero ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (0 );
958+         assertEq (rateZero, expectedMinPerEpoch, "0 bytes should return 0.06 USDFC/month minimum " );
959+ 
960+         // Test 1 GiB 
961+         (uint256  rateOneGiB ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (oneGiB);
962+         assertEq (rateOneGiB, expectedMinPerEpoch, "1 GiB should return minimum rate " );
963+ 
964+         // Test 10 GiB 
965+         (uint256  rateTenGiB ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (10  *  oneGiB);
966+         assertEq (rateTenGiB, expectedMinPerEpoch, "10 GiB should return minimum rate " );
967+ 
968+         // Test 24 GiB (below crossover) 
969+         (uint256  rateTwentyFourGiB ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (24  *  oneGiB);
970+         assertEq (rateTwentyFourGiB, expectedMinPerEpoch, "24 GiB should return minimum rate " );
971+     }
972+ 
973+     function testMinimumPricing_CrossoverPoint  () public  view  {
974+         // Test the crossover where natural pricing exceeds minimum 
975+         // At 2.5 USDFC/TiB: 0.06/2.5*1024 = 24.576 GiB is the crossover 
976+         uint256  oneGiB =  1024  *  1024  *  1024 ;
977+         uint256  decimals =  18 ;
978+         uint256  expectedMinPerMonth =  (6  *  10  **  decimals) /  100 ;
979+         uint256  expectedMinPerEpoch =  expectedMinPerMonth /  86400 ;
980+ 
981+         // 24 GiB: natural rate (0.0586) < minimum (0.06), so returns minimum 
982+         (uint256  rate24GiB ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (24  *  oneGiB);
983+         assertEq (rate24GiB, expectedMinPerEpoch, "24 GiB should use minimum floor " );
984+ 
985+         // 25 GiB: natural rate (0.0610) > minimum (0.06), so returns natural rate 
986+         (uint256  rate25GiB ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (25  *  oneGiB);
987+         assert (rate25GiB >  expectedMinPerEpoch);
988+ 
989+         // Verify it's actually proportional (not minimum) 
990+         uint256  expectedNatural25 =  rate25GiB *  86400 ; // Convert to monthly 
991+         uint256  expected25Monthly =  (25  *  10  **  decimals *  25 ) /  (1024  *  10 ); // 25 GiB at 2.5 USDFC/TiB 
992+         // Tolerance: actual loss is ~16,000 from integer division, allow 100,000 for safety 
993+         assertApproxEqAbs (expectedNatural25, expected25Monthly, 100000 , "25 GiB should use natural rate " );
994+     }
995+ 
996+     function testMinimumPricing_LargeDataSetsUseProportionalPricing  () public  view  {
997+         // Large datasets should use proportional pricing (natural rate > minimum) 
998+         uint256  oneGiB =  1024  *  1024  *  1024 ;
999+         uint256  decimals =  18 ;
1000+         uint256  expectedMinPerMonth =  (6  *  10  **  decimals) /  100 ;
1001+         uint256  expectedMinPerEpoch =  expectedMinPerMonth /  86400 ;
1002+ 
1003+         // Test 48 GiB 
1004+         (uint256  rate48GiB ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (48  *  oneGiB);
1005+         assert (rate48GiB >  expectedMinPerEpoch);
1006+ 
1007+         // Test 100 GiB 
1008+         (uint256  rate100GiB ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (100  *  oneGiB);
1009+         assert (rate100GiB >  rate48GiB);
1010+ 
1011+         // Test 1 TiB 
1012+         uint256  oneTiB =  oneGiB *  1024 ;
1013+         (uint256  rateOneTiB ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (oneTiB);
1014+         assert (rateOneTiB >  rate100GiB);
1015+ 
1016+         // Verify proportional scaling 
1017+         assertApproxEqRel (rate100GiB, rate48GiB *  100  /  48 , 0.01e18 , "Rates should scale proportionally " );
1018+     }
1019+ 
1020+     function testMinimumPricing_ExactlyPoint06USDFC  () public  view  {
1021+         // Verify that minimum pricing is exactly 0.06 USDFC/month for small datasets 
1022+         uint256  decimals =  18 ; // MockUSDFC uses 18 decimals in tests 
1023+         uint256  oneGiB =  1024  *  1024  *  1024 ;
1024+ 
1025+         // Get rate per epoch for dataset below crossover point 
1026+         (uint256  ratePerEpoch ,,) =  pdpServiceWithPayments.calculateRatesPerEpoch (oneGiB);
1027+ 
1028+         // Convert to rate per month (86400 epochs per month) 
1029+         uint256  ratePerMonth =  ratePerEpoch *  86400 ;
1030+ 
1031+         // Expected: exactly 0.06 USDFC with 18 decimals = 60000000000000000 
1032+         // Allow tiny tolerance for integer division rounding (0.06 / 86400 rounds down) 
1033+         uint256  expected =  (6  *  10  **  decimals) /  100 ;
1034+         uint256  tolerance =  1 ; // Allow 1 per epoch difference = 86400 total 
1035+ 
1036+         assertApproxEqAbs (ratePerMonth, expected, tolerance *  86400 , "Minimum rate should be 0.06 USDFC/month " );
1037+     }
1038+ 
1039+     function testMinimumPricing_CDNRatesUnaffected  () public  view  {
1040+         // Verify that CDN rates remain proportional (not affected by minimum pricing) 
1041+         uint256  oneGiB =  1024  *  1024  *  1024 ;
1042+ 
1043+         // Get rates for small dataset 
1044+         (, uint256  cacheMissRateSmall , uint256  cdnRateSmall ) =  pdpServiceWithPayments.calculateRatesPerEpoch (oneGiB);
1045+ 
1046+         // Get rates for larger dataset (12 GiB) 
1047+         (, uint256  cacheMissRateLarge , uint256  cdnRateLarge ) = 
1048+             pdpServiceWithPayments.calculateRatesPerEpoch (12  *  oneGiB);
1049+ 
1050+         // CDN rates should scale proportionally with size (allow small rounding tolerance) 
1051+         assertApproxEqAbs (
1052+             cacheMissRateLarge, cacheMissRateSmall *  12 , 100 , "Cache miss rate should scale proportionally " 
1053+         );
1054+         assertApproxEqAbs (cdnRateLarge, cdnRateSmall *  12 , 100 , "CDN rate should scale proportionally " );
9441055    }
9451056
9461057    uint256  nextClientDataSetId =  0 ;
@@ -971,9 +1082,9 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
9711082
9721083        // Setup client payment approval if not already done 
9731084        vm.startPrank (clientAddress);
974-         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e6 ,  1000e6 , 365  days);
975-         mockUSDFC.approve (address (payments), 100e6 );
976-         payments.deposit (mockUSDFC, clientAddress, 100e6 );
1085+         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e18 ,  1000e18 , 365  days);
1086+         mockUSDFC.approve (address (payments), 100e18 );
1087+         payments.deposit (mockUSDFC, clientAddress, 100e18 );
9771088        vm.stopPrank ();
9781089
9791090        // Create data set as approved provider 
@@ -1157,9 +1268,9 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
11571268
11581269        // Setup client payment approval if not already done 
11591270        vm.startPrank (clientAddress);
1160-         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e6 ,  1000e6 , 365  days);
1161-         mockUSDFC.approve (address (payments), 100e6 );
1162-         payments.deposit (mockUSDFC, clientAddress, 100e6 );
1271+         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e18 ,  1000e18 , 365  days);
1272+         mockUSDFC.approve (address (payments), 100e18 );
1273+         payments.deposit (mockUSDFC, clientAddress, 100e18 );
11631274        vm.stopPrank ();
11641275
11651276        // Create data set as approved provider 
@@ -1302,11 +1413,11 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
13021413            mockUSDFC,
13031414            address (pdpServiceWithPayments),
13041415            true ,
1305-             1000e6 , // rate allowance 
1306-             1000e6 , // lockup allowance 
1416+             1000e18 , // rate allowance 
1417+             1000e18 , // lockup allowance 
13071418            365  days  // max lockup period 
13081419        );
1309-         uint256  depositAmount =  100e6 ;
1420+         uint256  depositAmount =  100e18 ;
13101421        mockUSDFC.approve (address (payments), depositAmount);
13111422        payments.deposit (mockUSDFC, client, depositAmount);
13121423        vm.stopPrank ();
@@ -1482,11 +1593,11 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
14821593            mockUSDFC,
14831594            address (pdpServiceWithPayments),
14841595            true ,
1485-             1000e6 , // rate allowance 
1486-             1000e6 , // lockup allowance 
1596+             1000e18 , // rate allowance 
1597+             1000e18 , // lockup allowance 
14871598            365  days  // max lockup period 
14881599        );
1489-         uint256  depositAmount =  100e6 ;
1600+         uint256  depositAmount =  100e18 ;
14901601        mockUSDFC.approve (address (payments), depositAmount);
14911602        payments.deposit (mockUSDFC, client, depositAmount);
14921603        vm.stopPrank ();
@@ -1603,11 +1714,11 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
16031714            mockUSDFC,
16041715            address (pdpServiceWithPayments),
16051716            true ,
1606-             1000e6 , // rate allowance 
1607-             1000e6 , // lockup allowance 
1717+             1000e18 , // rate allowance 
1718+             1000e18 , // lockup allowance 
16081719            365  days  // max lockup period 
16091720        );
1610-         uint256  depositAmount =  100e6 ;
1721+         uint256  depositAmount =  100e18 ;
16111722        mockUSDFC.approve (address (payments), depositAmount);
16121723        payments.deposit (mockUSDFC, client, depositAmount);
16131724        vm.stopPrank ();
@@ -2822,8 +2933,8 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
28222933        );
28232934
28242935        vm.startPrank (client);
2825-         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e6 ,  1000e6 , 365  days);
2826-         uint256  depositAmount =  1e6 ;
2936+         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e18 ,  1000e18 , 365  days);
2937+         uint256  depositAmount =  1e18 ;
28272938        mockUSDFC.approve (address (payments), depositAmount);
28282939        payments.deposit (mockUSDFC, client, depositAmount);
28292940        vm.stopPrank ();
@@ -2875,8 +2986,8 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
28752986        );
28762987
28772988        vm.startPrank (client);
2878-         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e6 ,  1000e6 , 365  days);
2879-         uint256  depositAmount =  1e6 ;
2989+         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e18 ,  1000e18 , 365  days);
2990+         uint256  depositAmount =  1e18 ;
28802991        mockUSDFC.approve (address (payments), depositAmount);
28812992        payments.deposit (mockUSDFC, client, depositAmount);
28822993        vm.stopPrank ();
@@ -2926,8 +3037,8 @@ contract FilecoinWarmStorageServiceTest is MockFVMTest {
29263037        );
29273038
29283039        vm.startPrank (client);
2929-         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e6 ,  1000e6 , 365  days);
2930-         uint256  depositAmount =  10e6 ;
3040+         payments.setOperatorApproval (mockUSDFC, address (pdpServiceWithPayments), true , 1000e18 ,  1000e18 , 365  days);
3041+         uint256  depositAmount =  10e18 ;
29313042        mockUSDFC.approve (address (payments), depositAmount);
29323043        payments.deposit (mockUSDFC, client, depositAmount);
29333044        vm.stopPrank ();
@@ -4197,7 +4308,7 @@ contract FilecoinWarmStorageServiceSignatureTest is Test {
41974308        pdpService =  SignatureCheckingService (address (serviceProxy));
41984309
41994310        // Fund the payer 
4200-         mockUSDFC.safeTransfer (payer, 1000  *  10  **  6 ); // 1000 USDFC 
4311+         mockUSDFC.safeTransfer (payer, 1000  *  10  **  18 ); // 1000 USDFC 
42014312    }
42024313
42034314    // Test the recoverSigner function indirectly through signature verification 
0 commit comments