@@ -74,10 +74,11 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion {
7474 /// When a workflow is paused it is removed from the don family.
7575 mapping (bytes32 rid = > bytes32 donHash ) private s_donByWorkflowRid;
7676
77- /// @dev Tracking allowlisted requests for the owner address, required to enable anyone to verify off-chain requests.
78- mapping (bytes32 ownerDigestHash = > uint32 expiryTimestamp ) private s_requestsAllowlist;
79- /// @dev Storing allowlisted requests for all owners, enabling fetching all non-expired requests
80- OwnerAllowlistedRequest[] private s_requestAllowlistArray;
77+ /// @dev Fast lookup for allowlisted requests. Key is keccak256(abi.encode(owner, requestDigest)), value is (array_index + 1).
78+ /// We store index+1 so that 0 can represent "not found" (since array indices start at 0).
79+ mapping (bytes32 => uint256 ) private s_requestIndexMap;
80+ /// @dev Array storing all allowlisted request data for enumeration and pagination.
81+ OwnerAllowlistedRequest[] private s_requestData;
8182 /// @dev Map each owner address to their arbitrary config. Can be used to control billing parameters or any other data per owner
8283 mapping (address owner = > bytes config ) private s_ownerConfig;
8384
@@ -1278,10 +1279,23 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion {
12781279 }
12791280 if (! s_linkedOwners.contains (msg .sender )) revert OwnershipLinkDoesNotExist (msg .sender );
12801281
1281- s_requestsAllowlist[keccak256 (abi.encode (msg .sender , requestDigest))] = expiryTimestamp;
1282- s_requestAllowlistArray.push (
1283- OwnerAllowlistedRequest ({owner: msg .sender , requestDigest: requestDigest, expiryTimestamp: expiryTimestamp})
1284- );
1282+ bytes32 key = keccak256 (abi.encode (msg .sender , requestDigest));
1283+
1284+ // Check if this request already exists (0 means not found)
1285+ uint256 storedIndex = s_requestIndexMap[key];
1286+
1287+ if (storedIndex != 0 ) {
1288+ // Update existing entry in place (convert back to 0-based index)
1289+ s_requestData[storedIndex - 1 ].expiryTimestamp = expiryTimestamp;
1290+ } else {
1291+ // Create new entry
1292+ uint256 newIndex = s_requestData.length ;
1293+ s_requestData.push (
1294+ OwnerAllowlistedRequest ({owner: msg .sender , requestDigest: requestDigest, expiryTimestamp: expiryTimestamp})
1295+ );
1296+ // Store index+1 so that 0 can represent "not found"
1297+ s_requestIndexMap[key] = newIndex + 1 ;
1298+ }
12851299 emit RequestAllowlisted (msg .sender , requestDigest, expiryTimestamp);
12861300 }
12871301
@@ -1292,41 +1306,59 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion {
12921306 /// @param requestDigest Unique identifier for the request (hash of the request payload).
12931307 /// @return bool True if the request is allowlisted and not expired, false otherwise.
12941308 function isRequestAllowlisted (address owner , bytes32 requestDigest ) external view returns (bool ) {
1295- return s_requestsAllowlist[keccak256 (abi.encode (owner, requestDigest))] > block .timestamp ;
1296- }
1297-
1309+ bytes32 key = keccak256 (abi.encode (owner, requestDigest));
1310+ uint256 storedIndex = s_requestIndexMap[key];
1311+ if (storedIndex == 0 ) return false ; // Not found
1312+
1313+ OwnerAllowlistedRequest storage request = s_requestData[storedIndex - 1 ];
1314+ return request.expiryTimestamp > block .timestamp ;
1315+ }
1316+
1317+ /// @notice Returns a paginated list of allowlisted requests across all owners.
1318+ /// @dev - Reads a slice of the allowlisted requests starting at `start` and spanning up to `limit` elements.
1319+ /// - Expired entries (where `expiryTimestamp <= block.timestamp`) are filtered out.
1320+ /// - The returned array may therefore be shorter than `limit`.
1321+ /// - Does not revert on out-of-range pagination: if `start >= total`, returns an empty array.
1322+ /// @param start Zero-based index into the allowlist at which to begin.
1323+ /// @param limit Maximum number of entries to return from `start`.
1324+ /// @return allowlistedRequests Array of {requestDigest, owner, expiryTimestamp} structs
1325+ /// for all non-expired requests found in the page slice.
12981326 function getAllowlistedRequests (
12991327 uint256 start ,
13001328 uint256 limit
13011329 ) external view returns (OwnerAllowlistedRequest[] memory allowlistedRequests ) {
1302- uint256 total = s_requestAllowlistArray .length ;
1330+ uint256 total = s_requestData .length ;
13031331 uint256 pageCount = _getPageCount (total, start, limit);
13041332
13051333 if (pageCount == 0 ) return new OwnerAllowlistedRequest [](0 );
13061334
1307- allowlistedRequests = new OwnerAllowlistedRequest [](pageCount);
1308- uint256 addedCount = 0 ;
1335+ // First pass: count valid (non-expired) entries in the page range
1336+ uint256 validCount = 0 ;
13091337 for (uint256 i = 0 ; i < pageCount; ++ i) {
1310- OwnerAllowlistedRequest storage request = s_requestAllowlistArray [start + i];
1338+ OwnerAllowlistedRequest storage request = s_requestData [start + i];
13111339 if (request.expiryTimestamp > block .timestamp ) {
1312- allowlistedRequests[addedCount] = request;
1313- ++ addedCount;
1340+ ++ validCount;
13141341 }
13151342 }
13161343
1317- if (addedCount < pageCount) {
1318- OwnerAllowlistedRequest[] memory shrinkedList = new OwnerAllowlistedRequest [](addedCount);
1319- for (uint256 i = 0 ; i < addedCount; ++ i) {
1320- shrinkedList[i] = allowlistedRequests[i];
1344+ // Allocate exact size needed
1345+ allowlistedRequests = new OwnerAllowlistedRequest [](validCount);
1346+
1347+ // Second pass: populate the array with valid entries
1348+ uint256 addedCount = 0 ;
1349+ for (uint256 i = 0 ; i < pageCount; ++ i) {
1350+ OwnerAllowlistedRequest storage request = s_requestData[start + i];
1351+ if (request.expiryTimestamp > block .timestamp ) {
1352+ allowlistedRequests[addedCount] = request;
1353+ ++ addedCount;
13211354 }
1322- allowlistedRequests = shrinkedList;
13231355 }
13241356
13251357 return allowlistedRequests;
13261358 }
13271359
13281360 function totalAllowlistedRequests () external view returns (uint256 ) {
1329- return s_requestAllowlistArray .length ;
1361+ return s_requestData .length ;
13301362 }
13311363
13321364 // ================================================================
0 commit comments