@@ -334,15 +334,30 @@ contract FlowYieldVaultsRequestsTest is Test {
334334 assertEq (uint8 (req.status), uint8 (FlowYieldVaultsRequests.RequestStatus.PROCESSING));
335335 }
336336
337- function test_StartProcessingBatch_RevertNotPending () public {
337+ function test_StartProcessingBatch_RevertRequestNotInQueueWhenQueueEmpty () public {
338+ vm.startPrank (coa);
339+ vm.expectRevert (abi.encodeWithSelector (
340+ FlowYieldVaultsRequests.RequestNotInQueue.selector ,
341+ 1
342+ ));
343+ _startProcessingBatch (1 );
344+ vm.stopPrank ();
345+ }
346+
347+ function test_StartProcessingBatch_RevertRequestNotInQueueWhenQueueNonEmpty () public {
338348 vm.prank (user);
339349 uint256 reqId = c.createYieldVault {value: 1 ether }(NATIVE_FLOW, 1 ether, VAULT_ID, STRATEGY_ID);
340350
341351 vm.startPrank (coa);
342- _startProcessingBatch (reqId);
352+ uint256 [] memory successfulRequestIds = new uint256 [](5 );
353+ successfulRequestIds[0 ] = reqId;
354+ successfulRequestIds[1 ] = reqId+2 ;
343355
344- vm.expectRevert (FlowYieldVaultsRequests.InvalidRequestState.selector );
345- _startProcessingBatch (reqId);
356+ vm.expectRevert (abi.encodeWithSelector (
357+ FlowYieldVaultsRequests.RequestNotInQueue.selector ,
358+ reqId+2
359+ ));
360+ c.startProcessingBatch (successfulRequestIds, new uint256 [](0 ));
346361 vm.stopPrank ();
347362 }
348363
@@ -355,6 +370,36 @@ contract FlowYieldVaultsRequestsTest is Test {
355370 _startProcessingBatch (reqId);
356371 }
357372
373+ function test_StartProcessingBatch_WithMoreRequestIdsThanQueued () public {
374+ vm.startPrank (user);
375+ uint256 req1 = c.createYieldVault {value: 1 ether }(NATIVE_FLOW, 1 ether, VAULT_ID, STRATEGY_ID);
376+ uint256 req2 = c.createYieldVault {value: 2 ether }(NATIVE_FLOW, 2 ether, VAULT_ID, STRATEGY_ID);
377+ uint256 req3 = c.createYieldVault {value: 3 ether }(NATIVE_FLOW, 3 ether, VAULT_ID, STRATEGY_ID);
378+ vm.stopPrank ();
379+
380+ vm.prank (coa);
381+ uint256 [] memory successfulRequestIds = new uint256 [](5 );
382+ successfulRequestIds[0 ] = req1;
383+ successfulRequestIds[1 ] = req2;
384+ successfulRequestIds[2 ] = req3;
385+ successfulRequestIds[3 ] = req3+5 ;
386+ successfulRequestIds[4 ] = req3+10 ;
387+
388+ vm.expectRevert (abi.encodeWithSelector (
389+ FlowYieldVaultsRequests.RequestNotInQueue.selector ,
390+ req3+5
391+ ));
392+ c.startProcessingBatch (successfulRequestIds, new uint256 [](0 ));
393+
394+ (uint256 [] memory requestIds , , , , , , , , , , ) = c.getPendingRequestsUnpacked (0 , 0 );
395+ assertEq (requestIds.length , 3 );
396+
397+ for (uint256 i = 0 ; i < requestIds.length ; i++ ) {
398+ FlowYieldVaultsRequests.Request memory req = c.getRequest (successfulRequestIds[i]);
399+ assertEq (uint8 (req.status), uint8 (FlowYieldVaultsRequests.RequestStatus.PENDING));
400+ }
401+ }
402+
358403 function test_StartProcessingBatch_RevertRequestProcessOutOfOrder () public {
359404 vm.startPrank (user);
360405 uint256 req1 = c.createYieldVault {value: 1 ether }(NATIVE_FLOW, 1 ether, VAULT_ID, STRATEGY_ID);
@@ -378,19 +423,76 @@ contract FlowYieldVaultsRequestsTest is Test {
378423 uint256 req3 = c.createYieldVault {value: 3 ether }(NATIVE_FLOW, 3 ether, VAULT_ID, STRATEGY_ID);
379424 uint256 req4 = c.createYieldVault {value: 4 ether }(NATIVE_FLOW, 4 ether, VAULT_ID, STRATEGY_ID);
380425 uint256 req5 = c.createYieldVault {value: 5 ether }(NATIVE_FLOW, 5 ether, VAULT_ID, STRATEGY_ID);
426+ uint256 req6 = c.createYieldVault {value: 6 ether }(NATIVE_FLOW, 6 ether, VAULT_ID, STRATEGY_ID);
381427 vm.stopPrank ();
382428
383- vm.prank (coa);
384- // All 5 successful, transition to PROCESSING
385- uint256 [] memory successfulRequestIds = new uint256 [](5 );
429+ vm.startPrank (coa);
430+ // First 3 successful, transition to PROCESSING
431+ uint256 [] memory successfulRequestIds = new uint256 [](3 );
386432 successfulRequestIds[0 ] = req1;
387433 successfulRequestIds[1 ] = req2;
388434 successfulRequestIds[2 ] = req3;
389- successfulRequestIds[3 ] = req4;
390- successfulRequestIds[4 ] = req5;
391435 c.startProcessingBatch (successfulRequestIds, new uint256 [](0 ));
392436
393437 (uint256 [] memory requestIds , , , , , , , , , , ) = c.getPendingRequestsUnpacked (0 , 0 );
438+ assertEq (requestIds.length , 3 );
439+
440+ for (uint256 i = 0 ; i < successfulRequestIds.length ; i++ ) {
441+ FlowYieldVaultsRequests.Request memory req = c.getRequest (successfulRequestIds[i]);
442+ assertEq (uint8 (req.status), uint8 (FlowYieldVaultsRequests.RequestStatus.PROCESSING));
443+ }
444+
445+ // Remaining 3 successful, transition to PROCESSING
446+ successfulRequestIds[0 ] = req4;
447+ successfulRequestIds[1 ] = req5;
448+ successfulRequestIds[2 ] = req6;
449+ c.startProcessingBatch (successfulRequestIds, new uint256 [](0 ));
450+
451+ (requestIds, , , , , , , , , , ) = c.getPendingRequestsUnpacked (0 , 0 );
452+ assertEq (requestIds.length , 0 );
453+
454+ for (uint256 i = 0 ; i < successfulRequestIds.length ; i++ ) {
455+ FlowYieldVaultsRequests.Request memory req = c.getRequest (successfulRequestIds[i]);
456+ assertEq (uint8 (req.status), uint8 (FlowYieldVaultsRequests.RequestStatus.PROCESSING));
457+ }
458+ vm.stopPrank ();
459+ }
460+
461+ function test_StartProcessingBatch_WithUserCancellationRace () public {
462+ vm.startPrank (user);
463+ uint256 req1 = c.createYieldVault {value: 1 ether }(NATIVE_FLOW, 1 ether, VAULT_ID, STRATEGY_ID);
464+ uint256 req2 = c.createYieldVault {value: 2 ether }(NATIVE_FLOW, 2 ether, VAULT_ID, STRATEGY_ID);
465+ uint256 req3 = c.createYieldVault {value: 3 ether }(NATIVE_FLOW, 3 ether, VAULT_ID, STRATEGY_ID);
466+ c.cancelRequest (req2);
467+ vm.stopPrank ();
468+
469+ vm.startPrank (coa);
470+ // First and third requests, transition to PROCESSING
471+ uint256 [] memory successfulRequestIds = new uint256 [](2 );
472+ successfulRequestIds[0 ] = req1;
473+ successfulRequestIds[1 ] = req3;
474+ // Second request, transition to FAILED
475+ uint256 [] memory rejectedRequestIds = new uint256 [](1 );
476+ rejectedRequestIds[0 ] = req2;
477+
478+ vm.expectRevert (abi.encodeWithSelector (
479+ FlowYieldVaultsRequests.RequestNotInQueue.selector ,
480+ req2
481+ ));
482+ c.startProcessingBatch (successfulRequestIds, rejectedRequestIds);
483+
484+ (uint256 [] memory requestIds , , , , , , , , , , ) = c.getPendingRequestsUnpacked (0 , 0 );
485+ assertEq (requestIds.length , 2 );
486+
487+ for (uint256 i = 0 ; i < successfulRequestIds.length ; i++ ) {
488+ FlowYieldVaultsRequests.Request memory req = c.getRequest (successfulRequestIds[i]);
489+ assertEq (uint8 (req.status), uint8 (FlowYieldVaultsRequests.RequestStatus.PENDING));
490+ }
491+
492+ // Try again, without the user-cancelled request
493+ c.startProcessingBatch (successfulRequestIds, new uint256 [](0 ));
494+
495+ (requestIds, , , , , , , , , , ) = c.getPendingRequestsUnpacked (0 , 0 );
394496 assertEq (requestIds.length , 0 );
395497
396498 for (uint256 i = 0 ; i < successfulRequestIds.length ; i++ ) {
@@ -483,8 +585,8 @@ contract FlowYieldVaultsRequestsTest is Test {
483585
484586 vm.expectRevert (abi.encodeWithSelector (
485587 FlowYieldVaultsRequests.RequestProcessOutOfOrder.selector ,
486- req2, // the expected requestId, in the queue head, after rejections have already been removed
487- req3 // the provided requestId
588+ req2, // queue[head+1] — the current queue position that doesn't match either input array
589+ req4 // the first provided requestId, from successfulRequestIds
488590 ));
489591 c.startProcessingBatch (successfulRequestIds, rejectedRequestIds);
490592
@@ -525,7 +627,7 @@ contract FlowYieldVaultsRequestsTest is Test {
525627 vm.expectRevert (abi.encodeWithSelector (
526628 FlowYieldVaultsRequests.RequestProcessOutOfOrder.selector ,
527629 req1, // the expected requestId, in the queue head
528- req3 // the provided requestId
630+ req4 // the first provided requestId, from successfulRequestIds
529631 ));
530632 c.startProcessingBatch (successfulRequestIds, rejectedRequestIds);
531633
0 commit comments