From 068076fc295d07bfdd72ad17012cd03067f87323 Mon Sep 17 00:00:00 2001 From: Mark Toda Date: Mon, 21 Aug 2023 17:35:33 -0700 Subject: [PATCH] fix: enforce dutch decay actually decays Previously there was ambiguous undefined behavior for if startTime and endTime were the same - This commit removes that ambiguity by enforcing startTime !== endTime --- ...e-DutchOrder-BaseExecuteSingleWithFee.snap | 2 +- .../Base-DutchOrder-ExecuteBatch.snap | 2 +- ...utchOrder-ExecuteBatchMultipleOutputs.snap | 2 +- ...teBatchMultipleOutputsDifferentTokens.snap | 2 +- ...e-DutchOrder-ExecuteBatchNativeOutput.snap | 2 +- .../Base-DutchOrder-ExecuteSingle.snap | 2 +- ...-DutchOrder-ExecuteSingleNativeOutput.snap | 2 +- ...se-DutchOrder-ExecuteSingleValidation.snap | 2 +- ...veDutchOrder-BaseExecuteSingleWithFee.snap | 2 +- ...Base-ExclusiveDutchOrder-ExecuteBatch.snap | 2 +- ...utchOrder-ExecuteBatchMultipleOutputs.snap | 2 +- ...teBatchMultipleOutputsDifferentTokens.snap | 2 +- ...veDutchOrder-ExecuteBatchNativeOutput.snap | 2 +- ...ase-ExclusiveDutchOrder-ExecuteSingle.snap | 2 +- ...eDutchOrder-ExecuteSingleNativeOutput.snap | 2 +- ...iveDutchOrder-ExecuteSingleValidation.snap | 2 +- ...tOrderReactor-ExecuteSingleValidation.snap | 2 +- .../DirectFillerFillMacroSingleOrder.snap | 2 +- ...rectFillerFillMacroSingleOrderWithFee.snap | 2 +- .../DirectFillerFillMacroTestEth1Output.snap | 2 +- .../DirectFillerFillMacroTestEth2Outputs.snap | 2 +- ...ectFillerFillMacroThreeOrdersWithFees.snap | 2 +- .../DirectFillerFillMacroTwoOrders.snap | 2 +- ...tputTest3OrdersWithEthAndERC20Outputs.snap | 2 +- .forge-snapshots/EthOutputTestEthOutput.snap | 2 +- ...omparisonTest-InterfaceAndProtocolFee.snap | 2 +- ...Test-InterfaceAndProtocolFeeEthOutput.snap | 2 +- ...colFeesGasComparisonTest-InterfaceFee.snap | 2 +- ...sComparisonTest-InterfaceFeeEthOutput.snap | 2 +- .../ProtocolFeesGasComparisonTest-NoFees.snap | 2 +- ...FeesGasComparisonTest-NoFeesEthOutput.snap | 2 +- .../SwapRouter02ExecutorExecute.snap | 2 +- ...outer02ExecutorExecuteAlreadyApproved.snap | 2 +- .../testExclusiveFillerSucceeds.snap | 2 +- src/lib/DutchDecayLib.sol | 2 +- test/lib/DutchDecayLib.t.sol | 6 +++--- test/reactors/DutchOrderReactor.t.sol | 19 +++++++++++++++++-- 37 files changed, 55 insertions(+), 40 deletions(-) diff --git a/.forge-snapshots/Base-DutchOrder-BaseExecuteSingleWithFee.snap b/.forge-snapshots/Base-DutchOrder-BaseExecuteSingleWithFee.snap index e77e2b32..3468a356 100644 --- a/.forge-snapshots/Base-DutchOrder-BaseExecuteSingleWithFee.snap +++ b/.forge-snapshots/Base-DutchOrder-BaseExecuteSingleWithFee.snap @@ -1 +1 @@ -181978 \ No newline at end of file +181972 \ No newline at end of file diff --git a/.forge-snapshots/Base-DutchOrder-ExecuteBatch.snap b/.forge-snapshots/Base-DutchOrder-ExecuteBatch.snap index 333372f2..07a75158 100644 --- a/.forge-snapshots/Base-DutchOrder-ExecuteBatch.snap +++ b/.forge-snapshots/Base-DutchOrder-ExecuteBatch.snap @@ -1 +1 @@ -196879 \ No newline at end of file +196867 \ No newline at end of file diff --git a/.forge-snapshots/Base-DutchOrder-ExecuteBatchMultipleOutputs.snap b/.forge-snapshots/Base-DutchOrder-ExecuteBatchMultipleOutputs.snap index 8e513b1a..832da268 100644 --- a/.forge-snapshots/Base-DutchOrder-ExecuteBatchMultipleOutputs.snap +++ b/.forge-snapshots/Base-DutchOrder-ExecuteBatchMultipleOutputs.snap @@ -1 +1 @@ -206650 \ No newline at end of file +206635 \ No newline at end of file diff --git a/.forge-snapshots/Base-DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap b/.forge-snapshots/Base-DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap index 7db95251..300ff10a 100644 --- a/.forge-snapshots/Base-DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap +++ b/.forge-snapshots/Base-DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap @@ -1 +1 @@ -260307 \ No newline at end of file +260289 \ No newline at end of file diff --git a/.forge-snapshots/Base-DutchOrder-ExecuteBatchNativeOutput.snap b/.forge-snapshots/Base-DutchOrder-ExecuteBatchNativeOutput.snap index 91b52e86..f90f4d38 100644 --- a/.forge-snapshots/Base-DutchOrder-ExecuteBatchNativeOutput.snap +++ b/.forge-snapshots/Base-DutchOrder-ExecuteBatchNativeOutput.snap @@ -1 +1 @@ -190411 \ No newline at end of file +190399 \ No newline at end of file diff --git a/.forge-snapshots/Base-DutchOrder-ExecuteSingle.snap b/.forge-snapshots/Base-DutchOrder-ExecuteSingle.snap index 787d6f15..36e50fa2 100644 --- a/.forge-snapshots/Base-DutchOrder-ExecuteSingle.snap +++ b/.forge-snapshots/Base-DutchOrder-ExecuteSingle.snap @@ -1 +1 @@ -148194 \ No newline at end of file +148188 \ No newline at end of file diff --git a/.forge-snapshots/Base-DutchOrder-ExecuteSingleNativeOutput.snap b/.forge-snapshots/Base-DutchOrder-ExecuteSingleNativeOutput.snap index 22f39b41..908c50c9 100644 --- a/.forge-snapshots/Base-DutchOrder-ExecuteSingleNativeOutput.snap +++ b/.forge-snapshots/Base-DutchOrder-ExecuteSingleNativeOutput.snap @@ -1 +1 @@ -133756 \ No newline at end of file +133750 \ No newline at end of file diff --git a/.forge-snapshots/Base-DutchOrder-ExecuteSingleValidation.snap b/.forge-snapshots/Base-DutchOrder-ExecuteSingleValidation.snap index eb1b1759..7cc3b24f 100644 --- a/.forge-snapshots/Base-DutchOrder-ExecuteSingleValidation.snap +++ b/.forge-snapshots/Base-DutchOrder-ExecuteSingleValidation.snap @@ -1 +1 @@ -137605 \ No newline at end of file +157499 \ No newline at end of file diff --git a/.forge-snapshots/Base-ExclusiveDutchOrder-BaseExecuteSingleWithFee.snap b/.forge-snapshots/Base-ExclusiveDutchOrder-BaseExecuteSingleWithFee.snap index 2bbe0288..db6ccf79 100644 --- a/.forge-snapshots/Base-ExclusiveDutchOrder-BaseExecuteSingleWithFee.snap +++ b/.forge-snapshots/Base-ExclusiveDutchOrder-BaseExecuteSingleWithFee.snap @@ -1 +1 @@ -150633 \ No newline at end of file +182180 \ No newline at end of file diff --git a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatch.snap b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatch.snap index f6f06f29..92ae5a81 100644 --- a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatch.snap +++ b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatch.snap @@ -1 +1 @@ -197283 \ No newline at end of file +197271 \ No newline at end of file diff --git a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchMultipleOutputs.snap b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchMultipleOutputs.snap index 9817be4d..fe06891d 100644 --- a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchMultipleOutputs.snap +++ b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchMultipleOutputs.snap @@ -1 +1 @@ -207049 \ No newline at end of file +207034 \ No newline at end of file diff --git a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap index cecddc06..185e647a 100644 --- a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap +++ b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap @@ -1 +1 @@ -260720 \ No newline at end of file +260702 \ No newline at end of file diff --git a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchNativeOutput.snap b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchNativeOutput.snap index 8a0b978d..e4f9e911 100644 --- a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchNativeOutput.snap +++ b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteBatchNativeOutput.snap @@ -1 +1 @@ -190809 \ No newline at end of file +190797 \ No newline at end of file diff --git a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingle.snap b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingle.snap index 2f1f2ead..35af93c4 100644 --- a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingle.snap +++ b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingle.snap @@ -1 +1 @@ -148401 \ No newline at end of file +148395 \ No newline at end of file diff --git a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingleNativeOutput.snap b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingleNativeOutput.snap index 6abebf0f..391de7d7 100644 --- a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingleNativeOutput.snap +++ b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingleNativeOutput.snap @@ -1 +1 @@ -95568 \ No newline at end of file +133962 \ No newline at end of file diff --git a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingleValidation.snap b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingleValidation.snap index 433adecc..d58cce84 100644 --- a/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingleValidation.snap +++ b/.forge-snapshots/Base-ExclusiveDutchOrder-ExecuteSingleValidation.snap @@ -1 +1 @@ -157716 \ No newline at end of file +157710 \ No newline at end of file diff --git a/.forge-snapshots/Base-LimitOrderReactor-ExecuteSingleValidation.snap b/.forge-snapshots/Base-LimitOrderReactor-ExecuteSingleValidation.snap index 705a288b..ff76e7f8 100644 --- a/.forge-snapshots/Base-LimitOrderReactor-ExecuteSingleValidation.snap +++ b/.forge-snapshots/Base-LimitOrderReactor-ExecuteSingleValidation.snap @@ -1 +1 @@ -133743 \ No newline at end of file +153643 \ No newline at end of file diff --git a/.forge-snapshots/DirectFillerFillMacroSingleOrder.snap b/.forge-snapshots/DirectFillerFillMacroSingleOrder.snap index 788e6ee9..2333e480 100644 --- a/.forge-snapshots/DirectFillerFillMacroSingleOrder.snap +++ b/.forge-snapshots/DirectFillerFillMacroSingleOrder.snap @@ -1 +1 @@ -136213 \ No newline at end of file +136207 \ No newline at end of file diff --git a/.forge-snapshots/DirectFillerFillMacroSingleOrderWithFee.snap b/.forge-snapshots/DirectFillerFillMacroSingleOrderWithFee.snap index a3be623b..cb77df21 100644 --- a/.forge-snapshots/DirectFillerFillMacroSingleOrderWithFee.snap +++ b/.forge-snapshots/DirectFillerFillMacroSingleOrderWithFee.snap @@ -1 +1 @@ -175064 \ No newline at end of file +175055 \ No newline at end of file diff --git a/.forge-snapshots/DirectFillerFillMacroTestEth1Output.snap b/.forge-snapshots/DirectFillerFillMacroTestEth1Output.snap index 8a598ac3..d7257162 100644 --- a/.forge-snapshots/DirectFillerFillMacroTestEth1Output.snap +++ b/.forge-snapshots/DirectFillerFillMacroTestEth1Output.snap @@ -1 +1 @@ -147390 \ No newline at end of file +147384 \ No newline at end of file diff --git a/.forge-snapshots/DirectFillerFillMacroTestEth2Outputs.snap b/.forge-snapshots/DirectFillerFillMacroTestEth2Outputs.snap index 459c4aec..d1461c78 100644 --- a/.forge-snapshots/DirectFillerFillMacroTestEth2Outputs.snap +++ b/.forge-snapshots/DirectFillerFillMacroTestEth2Outputs.snap @@ -1 +1 @@ -170604 \ No newline at end of file +170592 \ No newline at end of file diff --git a/.forge-snapshots/DirectFillerFillMacroThreeOrdersWithFees.snap b/.forge-snapshots/DirectFillerFillMacroThreeOrdersWithFees.snap index f70c13b3..dec18c72 100644 --- a/.forge-snapshots/DirectFillerFillMacroThreeOrdersWithFees.snap +++ b/.forge-snapshots/DirectFillerFillMacroThreeOrdersWithFees.snap @@ -1 +1 @@ -435187 \ No newline at end of file +435160 \ No newline at end of file diff --git a/.forge-snapshots/DirectFillerFillMacroTwoOrders.snap b/.forge-snapshots/DirectFillerFillMacroTwoOrders.snap index e757a1e3..e99820cb 100644 --- a/.forge-snapshots/DirectFillerFillMacroTwoOrders.snap +++ b/.forge-snapshots/DirectFillerFillMacroTwoOrders.snap @@ -1 +1 @@ -255972 \ No newline at end of file +255957 \ No newline at end of file diff --git a/.forge-snapshots/EthOutputTest3OrdersWithEthAndERC20Outputs.snap b/.forge-snapshots/EthOutputTest3OrdersWithEthAndERC20Outputs.snap index e763cd96..8c579c43 100644 --- a/.forge-snapshots/EthOutputTest3OrdersWithEthAndERC20Outputs.snap +++ b/.forge-snapshots/EthOutputTest3OrdersWithEthAndERC20Outputs.snap @@ -1 +1 @@ -363478 \ No newline at end of file +363457 \ No newline at end of file diff --git a/.forge-snapshots/EthOutputTestEthOutput.snap b/.forge-snapshots/EthOutputTestEthOutput.snap index 3ccb41fb..55fbe58e 100644 --- a/.forge-snapshots/EthOutputTestEthOutput.snap +++ b/.forge-snapshots/EthOutputTestEthOutput.snap @@ -1 +1 @@ -156223 \ No newline at end of file +156217 \ No newline at end of file diff --git a/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceAndProtocolFee.snap b/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceAndProtocolFee.snap index e88d7024..57bb743a 100644 --- a/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceAndProtocolFee.snap +++ b/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceAndProtocolFee.snap @@ -1 +1 @@ -176915 \ No newline at end of file +176906 \ No newline at end of file diff --git a/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceAndProtocolFeeEthOutput.snap b/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceAndProtocolFeeEthOutput.snap index cb97d05b..0054a557 100644 --- a/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceAndProtocolFeeEthOutput.snap +++ b/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceAndProtocolFeeEthOutput.snap @@ -1 +1 @@ -162907 \ No newline at end of file +162898 \ No newline at end of file diff --git a/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceFee.snap b/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceFee.snap index a07a3f15..e9bf3c5a 100644 --- a/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceFee.snap +++ b/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceFee.snap @@ -1 +1 @@ -166046 \ No newline at end of file +166037 \ No newline at end of file diff --git a/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceFeeEthOutput.snap b/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceFeeEthOutput.snap index 775567bf..ecc6dc50 100644 --- a/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceFeeEthOutput.snap +++ b/.forge-snapshots/ProtocolFeesGasComparisonTest-InterfaceFeeEthOutput.snap @@ -1 +1 @@ -146873 \ No newline at end of file +146864 \ No newline at end of file diff --git a/.forge-snapshots/ProtocolFeesGasComparisonTest-NoFees.snap b/.forge-snapshots/ProtocolFeesGasComparisonTest-NoFees.snap index b769768a..db47f9a6 100644 --- a/.forge-snapshots/ProtocolFeesGasComparisonTest-NoFees.snap +++ b/.forge-snapshots/ProtocolFeesGasComparisonTest-NoFees.snap @@ -1 +1 @@ -149267 \ No newline at end of file +149261 \ No newline at end of file diff --git a/.forge-snapshots/ProtocolFeesGasComparisonTest-NoFeesEthOutput.snap b/.forge-snapshots/ProtocolFeesGasComparisonTest-NoFeesEthOutput.snap index 8e555832..0e01dbf2 100644 --- a/.forge-snapshots/ProtocolFeesGasComparisonTest-NoFeesEthOutput.snap +++ b/.forge-snapshots/ProtocolFeesGasComparisonTest-NoFeesEthOutput.snap @@ -1 +1 @@ -124929 \ No newline at end of file +124923 \ No newline at end of file diff --git a/.forge-snapshots/SwapRouter02ExecutorExecute.snap b/.forge-snapshots/SwapRouter02ExecutorExecute.snap index 33bb7d57..63bae837 100644 --- a/.forge-snapshots/SwapRouter02ExecutorExecute.snap +++ b/.forge-snapshots/SwapRouter02ExecutorExecute.snap @@ -1 +1 @@ -262973 \ No newline at end of file +262967 \ No newline at end of file diff --git a/.forge-snapshots/SwapRouter02ExecutorExecuteAlreadyApproved.snap b/.forge-snapshots/SwapRouter02ExecutorExecuteAlreadyApproved.snap index f78360f3..df1cb104 100644 --- a/.forge-snapshots/SwapRouter02ExecutorExecuteAlreadyApproved.snap +++ b/.forge-snapshots/SwapRouter02ExecutorExecuteAlreadyApproved.snap @@ -1 +1 @@ -118092 \ No newline at end of file +118086 \ No newline at end of file diff --git a/.forge-snapshots/testExclusiveFillerSucceeds.snap b/.forge-snapshots/testExclusiveFillerSucceeds.snap index 9a90a3d8..cf90b544 100644 --- a/.forge-snapshots/testExclusiveFillerSucceeds.snap +++ b/.forge-snapshots/testExclusiveFillerSucceeds.snap @@ -1 +1 @@ -174066 \ No newline at end of file +174060 \ No newline at end of file diff --git a/src/lib/DutchDecayLib.sol b/src/lib/DutchDecayLib.sol index 5b481875..2dd8ca37 100644 --- a/src/lib/DutchDecayLib.sol +++ b/src/lib/DutchDecayLib.sol @@ -28,7 +28,7 @@ library DutchDecayLib { view returns (uint256 decayedAmount) { - if (decayEndTime < decayStartTime) { + if (decayEndTime <= decayStartTime) { revert EndTimeBeforeStartTime(); } else if (decayEndTime <= block.timestamp) { decayedAmount = endAmount; diff --git a/test/lib/DutchDecayLib.t.sol b/test/lib/DutchDecayLib.t.sol index 414f3eb0..fa0f0013 100644 --- a/test/lib/DutchDecayLib.t.sol +++ b/test/lib/DutchDecayLib.t.sol @@ -6,7 +6,7 @@ import {DutchDecayLib} from "../../src/lib/DutchDecayLib.sol"; contract DutchDecayLibTest is Test { function testDutchDecayNoDecay(uint256 amount, uint256 decayStartTime, uint256 decayEndTime) public { - vm.assume(decayEndTime >= decayStartTime); + vm.assume(decayEndTime > decayStartTime); assertEq(DutchDecayLib.decay(amount, amount, decayStartTime, decayEndTime), amount); } @@ -78,7 +78,7 @@ contract DutchDecayLibTest is Test { public { vm.assume(endAmount > startAmount); - vm.assume(decayEndTime >= decayStartTime); + vm.assume(decayEndTime > decayStartTime); uint256 decayed = DutchDecayLib.decay(startAmount, endAmount, decayStartTime, decayEndTime); assertGe(decayed, startAmount); assertLe(decayed, endAmount); @@ -91,7 +91,7 @@ contract DutchDecayLibTest is Test { uint256 decayEndTime ) public { vm.assume(endAmount < startAmount); - vm.assume(decayEndTime >= decayStartTime); + vm.assume(decayEndTime > decayStartTime); uint256 decayed = DutchDecayLib.decay(startAmount, endAmount, decayStartTime, decayEndTime); assertLe(decayed, startAmount); assertGe(decayed, endAmount); diff --git a/test/reactors/DutchOrderReactor.t.sol b/test/reactors/DutchOrderReactor.t.sol index 0d39ef36..a78b8b76 100644 --- a/test/reactors/DutchOrderReactor.t.sol +++ b/test/reactors/DutchOrderReactor.t.sol @@ -160,13 +160,28 @@ contract DutchOrderReactorValidationTest is Test, DeployPermit2 { reactor.resolveOrder(SignedOrder(abi.encode(dlo), sig)); } - function testValidateDutchEndTimeAfterStart() public view { + function testValidateDutchEndTimeEqualStart() public { + vm.expectRevert(DutchDecayLib.EndTimeBeforeStartTime.selector); DutchOutput[] memory dutchOutputs = new DutchOutput[](1); dutchOutputs[0] = DutchOutput(address(0), 1000, 900, address(0)); DutchOrder memory dlo = DutchOrder( OrderInfoBuilder.init(address(reactor)).withDeadline(1659130540), - 1659120540, 1659130540, + 1659130540, + DutchInput(MockERC20(address(0)), 0, 0), + dutchOutputs + ); + bytes memory sig = hex"1234"; + reactor.resolveOrder(SignedOrder(abi.encode(dlo), sig)); + } + + function testValidateDutchEndTimeAfterStart() public view { + DutchOutput[] memory dutchOutputs = new DutchOutput[](1); + dutchOutputs[0] = DutchOutput(address(0), 1000, 900, address(0)); + DutchOrder memory dlo = DutchOrder( + OrderInfoBuilder.init(address(reactor)).withDeadline(1659130541), + 1659120540, + 1659130541, DutchInput(MockERC20(address(0)), 0, 0), dutchOutputs );