@@ -177,6 +177,11 @@ contract FilecoinWarmStorageService is
177177
178178 // Metadata key constants
179179 string private constant METADATA_KEY_WITH_CDN = "withCDN " ;
180+ uint256 private constant METADATA_KEY_WITH_CDN_SIZE = 7 ;
181+ bytes32 private constant METADATA_KEY_WITH_CDN_HASH = keccak256 ("withCDN " );
182+ // solidity storage representation of string "withCDN"
183+ bytes32 private constant WITH_CDN_STRING_STORAGE_REPR =
184+ 0x7769746843444e0000000000000000000000000000000000000000000000000e ;
180185
181186 // Pricing constants
182187 uint256 private immutable STORAGE_PRICE_PER_TIB_PER_MONTH; // 5 USDFC per TiB per month without CDN with correct decimals
@@ -608,7 +613,7 @@ contract FilecoinWarmStorageService is
608613 uint256 cacheMissRailId = 0 ;
609614 uint256 cdnRailId = 0 ;
610615
611- if (hasMetadataKey (createData.metadataKeys, METADATA_KEY_WITH_CDN )) {
616+ if (hasCDNMetadataKey (createData.metadataKeys)) {
612617 cacheMissRailId = payments.createRail (
613618 usdfcTokenAddress, // token address
614619 createData.payer, // from (payer)
@@ -694,7 +699,7 @@ contract FilecoinWarmStorageService is
694699
695700 // Clean up rail mappings
696701 delete railToDataSet[info.pdpRailId];
697- if (hasMetadataKey (dataSetMetadataKeys[dataSetId], METADATA_KEY_WITH_CDN )) {
702+ if (hasCDNMetadataKey (dataSetMetadataKeys[dataSetId])) {
698703 delete railToDataSet[info.cacheMissRailId];
699704 delete railToDataSet[info.cdnRailId];
700705 }
@@ -994,12 +999,11 @@ contract FilecoinWarmStorageService is
994999
9951000 payments.terminateRail (info.pdpRailId);
9961001
997- if (hasMetadataKey (dataSetMetadataKeys[dataSetId], METADATA_KEY_WITH_CDN )) {
1002+ if (deleteCDNMetadataKey (dataSetMetadataKeys[dataSetId])) {
9981003 payments.terminateRail (info.cacheMissRailId);
9991004 payments.terminateRail (info.cdnRailId);
10001005
10011006 // Delete withCDN flag from metadata to prevent further CDN operations
1002- dataSetMetadataKeys[dataSetId] = deleteMetadataKey (dataSetMetadataKeys[dataSetId], METADATA_KEY_WITH_CDN);
10031007 delete dataSetMetadata[dataSetId][METADATA_KEY_WITH_CDN];
10041008
10051009 emit CDNServiceTerminated (msg .sender , dataSetId, info.cacheMissRailId, info.cdnRailId);
@@ -1050,10 +1054,7 @@ contract FilecoinWarmStorageService is
10501054 require (msg .sender == info.payer, Errors.CallerNotPayer (dataSetId, info.payer, msg .sender ));
10511055
10521056 // Check if CDN service is configured
1053- require (
1054- hasMetadataKey (dataSetMetadataKeys[dataSetId], METADATA_KEY_WITH_CDN),
1055- Errors.FilBeamServiceNotConfigured (dataSetId)
1056- );
1057+ require (hasCDNMetadataKey (dataSetMetadataKeys[dataSetId]), Errors.FilBeamServiceNotConfigured (dataSetId));
10571058
10581059 // Check if cache miss and CDN rails are configured
10591060 require (info.cacheMissRailId != 0 && info.cdnRailId != 0 , Errors.InvalidDataSetId (dataSetId));
@@ -1085,10 +1086,7 @@ contract FilecoinWarmStorageService is
10851086
10861087 function terminateCDNService (uint256 dataSetId ) external onlyFilBeamController {
10871088 // Check if CDN service is configured
1088- require (
1089- hasMetadataKey (dataSetMetadataKeys[dataSetId], METADATA_KEY_WITH_CDN),
1090- Errors.FilBeamServiceNotConfigured (dataSetId)
1091- );
1089+ require (deleteCDNMetadataKey (dataSetMetadataKeys[dataSetId]), Errors.FilBeamServiceNotConfigured (dataSetId));
10921090
10931091 // Check if cache miss and CDN rails are configured
10941092 DataSetInfo storage info = dataSetInfo[dataSetId];
@@ -1099,7 +1097,6 @@ contract FilecoinWarmStorageService is
10991097 payments.terminateRail (info.cdnRailId);
11001098
11011099 // Delete withCDN flag from metadata to prevent further CDN operations
1102- dataSetMetadataKeys[dataSetId] = deleteMetadataKey (dataSetMetadataKeys[dataSetId], METADATA_KEY_WITH_CDN);
11031100 delete dataSetMetadata[dataSetId][METADATA_KEY_WITH_CDN];
11041101
11051102 emit CDNServiceTerminated (msg .sender , dataSetId, info.cacheMissRailId, info.cdnRailId);
@@ -1147,7 +1144,7 @@ contract FilecoinWarmStorageService is
11471144 emit RailRateUpdated (dataSetId, pdpRailId, newStorageRatePerEpoch);
11481145
11491146 // Update the CDN rail payment rates, if applicable
1150- if (hasMetadataKey (dataSetMetadataKeys[dataSetId], METADATA_KEY_WITH_CDN )) {
1147+ if (hasCDNMetadataKey (dataSetMetadataKeys[dataSetId])) {
11511148 (uint256 newCacheMissRatePerEpoch , uint256 newCDNRatePerEpoch ) = _calculateCDNRates (totalBytes);
11521149
11531150 uint256 cacheMissRailId = dataSetInfo[dataSetId].cacheMissRailId;
@@ -1308,19 +1305,17 @@ contract FilecoinWarmStorageService is
13081305 }
13091306
13101307 /**
1311- * @notice Returns true if ` key` exists in `metadataKeys`.
1308+ * @notice Returns true if key `withCDN ` exists in `metadataKeys`.
13121309 * @param metadataKeys The array of metadata keys
1313- * @param key The metadata key to look up
13141310 * @return True if key exists; false otherwise.
13151311 */
1316- function hasMetadataKey (string [] memory metadataKeys , string memory key ) internal pure returns (bool ) {
1317- bytes memory keyBytes = bytes (key);
1318- uint256 keyLength = keyBytes.length ;
1319- bytes32 keyHash = keccak256 (keyBytes);
1320-
1312+ function hasCDNMetadataKey (string [] memory metadataKeys ) internal pure returns (bool ) {
13211313 for (uint256 i = 0 ; i < metadataKeys.length ; i++ ) {
13221314 bytes memory currentKeyBytes = bytes (metadataKeys[i]);
1323- if (currentKeyBytes.length == keyLength && keccak256 (currentKeyBytes) == keyHash) {
1315+ if (
1316+ currentKeyBytes.length == METADATA_KEY_WITH_CDN_SIZE
1317+ && keccak256 (currentKeyBytes) == METADATA_KEY_WITH_CDN_HASH
1318+ ) {
13241319 return true ;
13251320 }
13261321 }
@@ -1330,37 +1325,27 @@ contract FilecoinWarmStorageService is
13301325 }
13311326
13321327 /**
1333- * @notice Deletes `key` if it exists in `metadataKeys`.
1334- * @param metadataKeys The array of metadata keys
1335- * @param key The metadata key to delete
1336- * @return Modified array of metadata keys
1328+ * @notice Deletes key `withCDN` if it exists in `metadataKeys`.
1329+ * @param metadataKeys The array of metadata keys to modify
1330+ * @return found Whether the withCDN key was deleted
13371331 */
1338- function deleteMetadataKey (string [] memory metadataKeys , string memory key )
1339- internal
1340- pure
1341- returns (string [] memory )
1342- {
1343- bytes memory keyBytes = bytes (key);
1344- uint256 keyLength = keyBytes.length ;
1345- bytes32 keyHash = keccak256 (keyBytes);
1346-
1347- uint256 len = metadataKeys.length ;
1348- for (uint256 i = 0 ; i < len; i++ ) {
1349- bytes memory currentKeyBytes = bytes (metadataKeys[i]);
1350- if (currentKeyBytes.length == keyLength && keccak256 (currentKeyBytes) == keyHash) {
1351- // Shift elements left to fill the gap
1352- for (uint256 j = i; j < len - 1 ; j++ ) {
1353- metadataKeys[j] = metadataKeys[j + 1 ];
1332+ function deleteCDNMetadataKey (string [] storage metadataKeys ) internal returns (bool found ) {
1333+ unchecked {
1334+ uint256 len = metadataKeys.length ;
1335+ for (uint256 i = 0 ; i < len; i++ ) {
1336+ string storage metadataKey = metadataKeys[i];
1337+ bytes32 repr;
1338+ assembly ("memory-safe" ) {
1339+ repr := sload (metadataKey.slot)
13541340 }
1355-
1356- delete metadataKeys[len - 1 ];
1357- assembly {
1358- mstore (metadataKeys, sub (len, 1 ))
1341+ if (repr == WITH_CDN_STRING_STORAGE_REPR) {
1342+ metadataKey = metadataKeys[len - 1 ];
1343+ metadataKeys. pop ();
1344+ return true ;
13591345 }
1360- break ;
13611346 }
13621347 }
1363- return metadataKeys ;
1348+ return false ;
13641349 }
13651350
13661351 /**
0 commit comments