Skip to content

Commit 7ce6cd4

Browse files
feat: paginate getApprovedProviders with test coverage (#238)
1 parent fa34673 commit 7ce6cd4

6 files changed

+259
-26
lines changed

service_contracts/abi/FilecoinWarmStorageServiceStateLibrary.abi.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@
156156
"name": "service",
157157
"type": "FilecoinWarmStorageService",
158158
"internalType": "contract FilecoinWarmStorageService"
159+
},
160+
{
161+
"name": "offset",
162+
"type": "uint256",
163+
"internalType": "uint256"
164+
},
165+
{
166+
"name": "limit",
167+
"type": "uint256",
168+
"internalType": "uint256"
159169
}
160170
],
161171
"outputs": [
@@ -167,6 +177,25 @@
167177
],
168178
"stateMutability": "view"
169179
},
180+
{
181+
"type": "function",
182+
"name": "getApprovedProvidersLength",
183+
"inputs": [
184+
{
185+
"name": "service",
186+
"type": "FilecoinWarmStorageService",
187+
"internalType": "contract FilecoinWarmStorageService"
188+
}
189+
],
190+
"outputs": [
191+
{
192+
"name": "count",
193+
"type": "uint256",
194+
"internalType": "uint256"
195+
}
196+
],
197+
"stateMutability": "view"
198+
},
170199
{
171200
"type": "function",
172201
"name": "getChallengesPerProof",

service_contracts/abi/FilecoinWarmStorageServiceStateView.abi.json

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,18 @@
130130
{
131131
"type": "function",
132132
"name": "getApprovedProviders",
133-
"inputs": [],
133+
"inputs": [
134+
{
135+
"name": "offset",
136+
"type": "uint256",
137+
"internalType": "uint256"
138+
},
139+
{
140+
"name": "limit",
141+
"type": "uint256",
142+
"internalType": "uint256"
143+
}
144+
],
134145
"outputs": [
135146
{
136147
"name": "providerIds",
@@ -140,6 +151,19 @@
140151
],
141152
"stateMutability": "view"
142153
},
154+
{
155+
"type": "function",
156+
"name": "getApprovedProvidersLength",
157+
"inputs": [],
158+
"outputs": [
159+
{
160+
"name": "count",
161+
"type": "uint256",
162+
"internalType": "uint256"
163+
}
164+
],
165+
"stateMutability": "view"
166+
},
143167
{
144168
"type": "function",
145169
"name": "getChallengesPerProof",

service_contracts/src/FilecoinWarmStorageServiceStateView.sol

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ contract FilecoinWarmStorageServiceStateView is IPDPProvingSchedule {
5050
return service.getAllPieceMetadata(dataSetId, pieceId);
5151
}
5252

53-
function getApprovedProviders() external view returns (uint256[] memory providerIds) {
54-
return service.getApprovedProviders();
53+
function getApprovedProviders(uint256 offset, uint256 limit) external view returns (uint256[] memory providerIds) {
54+
return service.getApprovedProviders(offset, limit);
55+
}
56+
57+
function getApprovedProvidersLength() external view returns (uint256 count) {
58+
return service.getApprovedProvidersLength();
5559
}
5660

5761
function getChallengesPerProof() external pure returns (uint64) {

service_contracts/src/lib/FilecoinWarmStorageServiceStateInternalLibrary.sol

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -415,28 +415,55 @@ library FilecoinWarmStorageServiceStateInternalLibrary {
415415
}
416416

417417
/**
418-
* @notice Get all approved provider IDs
418+
* @notice Get approved provider IDs with optional pagination
419419
* @param service The service contract
420-
* @return providerIds Array of all approved provider IDs
420+
* @param offset Starting index (0-based). Use 0 to start from beginning
421+
* @param limit Maximum number of providers to return. Use 0 to get all remaining providers
422+
* @return providerIds Array of approved provider IDs
423+
* @dev For large lists, use pagination to avoid gas limit issues. If limit=0,
424+
* returns all remaining providers starting from offset. Example:
425+
* getApprovedProviders(service, 0, 100) gets first 100 providers.
421426
*/
422-
function getApprovedProviders(FilecoinWarmStorageService service)
427+
function getApprovedProviders(FilecoinWarmStorageService service, uint256 offset, uint256 limit)
423428
internal
424429
view
425430
returns (uint256[] memory providerIds)
426431
{
427432
bytes32 slot = StorageLayout.APPROVED_PROVIDER_IDS_SLOT;
428-
uint256 length = uint256(service.extsload(slot));
433+
uint256 totalLength = uint256(service.extsload(slot));
429434

430-
if (length == 0) {
435+
if (totalLength == 0) {
431436
return new uint256[](0);
432437
}
433438

434-
bytes32[] memory result = service.extsloadStruct(keccak256(abi.encode(slot)), length);
439+
if (offset >= totalLength) {
440+
return new uint256[](0);
441+
}
442+
443+
uint256 actualLength = limit;
444+
if (limit == 0 || offset + limit > totalLength) {
445+
actualLength = totalLength - offset;
446+
}
447+
448+
bytes32 baseSlot = keccak256(abi.encode(slot));
449+
bytes32 startSlot = bytes32(uint256(baseSlot) + offset);
450+
bytes32[] memory paginatedResult = service.extsloadStruct(startSlot, actualLength);
451+
435452
assembly ("memory-safe") {
436-
providerIds := result
453+
providerIds := paginatedResult
437454
}
438455
}
439456

457+
/**
458+
* @notice Get the total number of approved providers
459+
* @param service The service contract
460+
* @return count Total number of approved providers
461+
*/
462+
function getApprovedProvidersLength(FilecoinWarmStorageService service) internal view returns (uint256 count) {
463+
bytes32 slot = StorageLayout.APPROVED_PROVIDER_IDS_SLOT;
464+
return uint256(service.extsload(slot));
465+
}
466+
440467
/**
441468
* @notice Get the FilBeam Controller address
442469
* @param service The service contract

service_contracts/src/lib/FilecoinWarmStorageServiceStateLibrary.sol

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -411,28 +411,55 @@ library FilecoinWarmStorageServiceStateLibrary {
411411
}
412412

413413
/**
414-
* @notice Get all approved provider IDs
414+
* @notice Get approved provider IDs with optional pagination
415415
* @param service The service contract
416-
* @return providerIds Array of all approved provider IDs
416+
* @param offset Starting index (0-based). Use 0 to start from beginning
417+
* @param limit Maximum number of providers to return. Use 0 to get all remaining providers
418+
* @return providerIds Array of approved provider IDs
419+
* @dev For large lists, use pagination to avoid gas limit issues. If limit=0,
420+
* returns all remaining providers starting from offset. Example:
421+
* getApprovedProviders(service, 0, 100) gets first 100 providers.
417422
*/
418-
function getApprovedProviders(FilecoinWarmStorageService service)
423+
function getApprovedProviders(FilecoinWarmStorageService service, uint256 offset, uint256 limit)
419424
public
420425
view
421426
returns (uint256[] memory providerIds)
422427
{
423428
bytes32 slot = StorageLayout.APPROVED_PROVIDER_IDS_SLOT;
424-
uint256 length = uint256(service.extsload(slot));
429+
uint256 totalLength = uint256(service.extsload(slot));
425430

426-
if (length == 0) {
431+
if (totalLength == 0) {
427432
return new uint256[](0);
428433
}
429434

430-
bytes32[] memory result = service.extsloadStruct(keccak256(abi.encode(slot)), length);
435+
if (offset >= totalLength) {
436+
return new uint256[](0);
437+
}
438+
439+
uint256 actualLength = limit;
440+
if (limit == 0 || offset + limit > totalLength) {
441+
actualLength = totalLength - offset;
442+
}
443+
444+
bytes32 baseSlot = keccak256(abi.encode(slot));
445+
bytes32 startSlot = bytes32(uint256(baseSlot) + offset);
446+
bytes32[] memory paginatedResult = service.extsloadStruct(startSlot, actualLength);
447+
431448
assembly ("memory-safe") {
432-
providerIds := result
449+
providerIds := paginatedResult
433450
}
434451
}
435452

453+
/**
454+
* @notice Get the total number of approved providers
455+
* @param service The service contract
456+
* @return count Total number of approved providers
457+
*/
458+
function getApprovedProvidersLength(FilecoinWarmStorageService service) public view returns (uint256 count) {
459+
bytes32 slot = StorageLayout.APPROVED_PROVIDER_IDS_SLOT;
460+
return uint256(service.extsload(slot));
461+
}
462+
436463
/**
437464
* @notice Get the FilBeam Controller address
438465
* @param service The service contract

0 commit comments

Comments
 (0)