@@ -167,16 +167,69 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
167167 /// @notice All requests indexed by request ID
168168 mapping (uint256 => Request) public requests;
169169
170- /// @notice Array of pending request IDs awaiting processing (FIFO order)
171- uint256 [] public pendingRequestIds;
172-
173- /// @notice Index of request ID in global pending array (for O(1) lookup)
174- mapping (uint256 => uint256 ) private _requestIndexInGlobalArray;
175-
176170 /// @notice Index of yieldVaultId in user's yieldVaultsByUser array (for O(1) removal)
177171 /// @dev Internal visibility allows test helpers to properly initialize state
178172 mapping (address => mapping (uint64 => uint256 )) internal _yieldVaultIndexInUserArray;
179173
174+ mapping (uint256 => uint256 ) queue;
175+ uint256 first = 1 ;
176+ uint256 last = 1 ;
177+
178+ function _enqueue (uint256 requestId ) internal {
179+ // empty queue
180+ if (first == last) {
181+ queue[first] = requestId;
182+ } else {
183+ queue[last] = requestId;
184+ }
185+ last += 1 ;
186+ }
187+
188+ function _dequeue () internal returns (uint256 ) {
189+ require (last > first);
190+
191+ uint256 requestId;
192+ requestId = queue[first];
193+
194+ delete queue[first];
195+ first += 1 ;
196+
197+ return requestId;
198+ }
199+
200+ function _drop (uint256 requestId ) internal {
201+ bool slide = false ;
202+ for (uint256 i = first; i <= last;) {
203+ if (queue[i] == requestId) {
204+ delete queue[i];
205+ slide = true ;
206+ }
207+
208+ if (slide) {
209+ queue[i] = queue[i+1 ];
210+ }
211+
212+ unchecked {
213+ ++ i;
214+ }
215+ }
216+
217+ last -= 1 ;
218+ }
219+
220+ function _peek () internal view returns (uint256 ) {
221+ require (last > first);
222+
223+ uint256 requestId;
224+ requestId = queue[first];
225+
226+ return requestId;
227+ }
228+
229+ function _queueLength () internal view returns (uint256 ) {
230+ return last - first;
231+ }
232+
180233 // ============================================
181234 // Errors
182235 // ============================================
@@ -728,6 +781,7 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
728781
729782 // Remove from pending queues (both global and user-specific)
730783 _removePendingRequest (requestId);
784+ _drop (requestId);
731785
732786 emit RequestProcessed (
733787 requestId,
@@ -929,6 +983,7 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
929983 userPendingRequestCount[request.user]-- ;
930984 }
931985 _removePendingRequest (requestId);
986+ _drop (requestId);
932987
933988 // === REFUND HANDLING (pull pattern) ===
934989 // For CREATE/DEPOSIT requests, move funds from pendingUserBalances to claimableRefunds
@@ -1008,9 +1063,11 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
10081063 * - Funds will be bridged back from Cadence in completeProcessing
10091064 *
10101065 * The PROCESSING status prevents request cancellation and double-processing.
1011- * @param requestId The unique identifier of the request to start processing.
1066+ * @param a The unique identifier of the request to start processing.
10121067 */
1013- function startProcessing (uint256 requestId ) external onlyAuthorizedCOA nonReentrant {
1068+ function startProcessing (uint256 a ) external onlyAuthorizedCOA nonReentrant {
1069+ // Pick the request at the front of the queue, for processing
1070+ uint256 requestId = _peek ();
10141071 Request storage request = requests[requestId];
10151072
10161073 // === VALIDATION ===
@@ -1094,17 +1151,19 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
10941151 * - Successful CLOSE: Unregisters YieldVault ownership
10951152 *
10961153 * For all other cases (success, WITHDRAW/CLOSE), msg.value must be 0.
1097- * @param requestId The unique identifier of the request to complete.
1154+ * @param a The unique identifier of the request to complete.
10981155 * @param success True if the Cadence operation succeeded, false otherwise.
10991156 * @param yieldVaultId The YieldVault Id from Cadence (for CREATE: newly assigned; for others: existing).
11001157 * @param message Human-readable status message or error description.
11011158 */
11021159 function completeProcessing (
1103- uint256 requestId ,
1160+ uint256 a ,
11041161 bool success ,
11051162 uint64 yieldVaultId ,
11061163 string calldata message
11071164 ) external payable onlyAuthorizedCOA nonReentrant {
1165+ // Pick the request at the front of the queue, for processing
1166+ uint256 requestId = _peek ();
11081167 Request storage request = requests[requestId];
11091168
11101169 // === VALIDATION ===
@@ -1181,6 +1240,7 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
11811240 userPendingRequestCount[request.user]-- ;
11821241 }
11831242 _removePendingRequest (requestId);
1243+ _dequeue ();
11841244
11851245 emit RequestProcessed (requestId, request.user, request.requestType, newStatus, yieldVaultId, message);
11861246 }
@@ -1222,12 +1282,19 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
12221282 /// @notice Gets the count of pending requests
12231283 /// @return Number of pending requests
12241284 function getPendingRequestCount () external view returns (uint256 ) {
1225- return pendingRequestIds. length ;
1285+ return _queueLength () ;
12261286 }
12271287
12281288 /// @notice Gets all pending request IDs
12291289 /// @return Array of pending request IDs
12301290 function getPendingRequestIds () external view returns (uint256 [] memory ) {
1291+ uint256 [] memory pendingRequestIds = new uint256 [](_queueLength ());
1292+ for (uint256 i = first; i <= last;) {
1293+ pendingRequestIds[i] = queue[i];
1294+ unchecked {
1295+ ++ i;
1296+ }
1297+ }
12311298 return pendingRequestIds;
12321299 }
12331300
@@ -1266,7 +1333,7 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
12661333 string [] memory strategyIdentifiers
12671334 )
12681335 {
1269- if (startIndex >= pendingRequestIds. length ) {
1336+ if (startIndex >= _queueLength () ) {
12701337 return (
12711338 new uint256 [](0 ),
12721339 new address [](0 ),
@@ -1282,7 +1349,7 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
12821349 );
12831350 }
12841351
1285- uint256 remaining = pendingRequestIds. length - startIndex;
1352+ uint256 remaining = _queueLength () - startIndex;
12861353 uint256 size = count == 0
12871354 ? remaining
12881355 : (count < remaining ? count : remaining);
@@ -1299,8 +1366,8 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
12991366 vaultIdentifiers = new string [](size);
13001367 strategyIdentifiers = new string [](size);
13011368
1302- for (uint256 i = 0 ; i < size; ) {
1303- Request memory req = requests[pendingRequestIds[ startIndex + i]];
1369+ for (uint256 i = 0 ; i < size;) {
1370+ Request memory req = requests[queue[first + startIndex + i]];
13041371 ids[i] = req.id;
13051372 users[i] = req.user;
13061373 requestTypes[i] = uint8 (req.requestType);
@@ -1672,8 +1739,7 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
16721739 });
16731740
16741741 // Add to global pending queue with index tracking for O(1) lookup
1675- _requestIndexInGlobalArray[requestId] = pendingRequestIds.length ;
1676- pendingRequestIds.push (requestId);
1742+ _enqueue (requestId);
16771743 userPendingRequestCount[msg .sender ]++ ;
16781744
16791745 // Add to user's pending array with index tracking for O(1) removal
@@ -1719,29 +1785,6 @@ contract FlowYieldVaultsRequests is ReentrancyGuard, Ownable2Step {
17191785 * @param requestId The request ID to remove from pending queues.
17201786 */
17211787 function _removePendingRequest (uint256 requestId ) internal {
1722- // === GLOBAL PENDING ARRAY REMOVAL ===
1723- // Uses O(1) lookup + O(n) shift to maintain FIFO order
1724- // FIFO order is critical for DeFi fairness - requests must be processed in submission order
1725- uint256 indexInGlobal = _requestIndexInGlobalArray[requestId];
1726- uint256 globalLength = pendingRequestIds.length ;
1727-
1728- // Safety check: verify element exists at expected index
1729- if (globalLength > 0 && indexInGlobal < globalLength && pendingRequestIds[indexInGlobal] == requestId) {
1730- // Shift all subsequent elements left to maintain FIFO order
1731- for (uint256 j = indexInGlobal; j < globalLength - 1 ; ) {
1732- pendingRequestIds[j] = pendingRequestIds[j + 1 ];
1733- // Update index mapping for each shifted element
1734- _requestIndexInGlobalArray[pendingRequestIds[j]] = j;
1735- unchecked {
1736- ++ j;
1737- }
1738- }
1739- // Remove the last element (now duplicated or the one to remove)
1740- pendingRequestIds.pop ();
1741- // Clean up index mapping
1742- delete _requestIndexInGlobalArray[requestId];
1743- }
1744-
17451788 // === USER PENDING ARRAY REMOVAL ===
17461789 // Uses swap-and-pop for O(1) removal (order doesn't affect FIFO processing)
17471790 address user = requests[requestId].user;
0 commit comments