From ac1d68e4ab2a9d3014ecd8631162ddbc2355fd39 Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:57:19 -0500 Subject: [PATCH 1/9] fix: EIP-712 nested types hash (#281) * fix: EIP-712 nested types hash * style: lint * test: assert eip 712 type hashes --- src/lib/V3DutchOrderLib.sol | 6 +++-- test/lib/EIP712.t.sol | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 test/lib/EIP712.t.sol diff --git a/src/lib/V3DutchOrderLib.sol b/src/lib/V3DutchOrderLib.sol index 41798218..8350cadd 100644 --- a/src/lib/V3DutchOrderLib.sol +++ b/src/lib/V3DutchOrderLib.sol @@ -95,7 +95,8 @@ library V3DutchOrderLib { "uint256 maxAmount,", "uint256 adjustmentPerGweiBaseFee)" ); - bytes32 internal constant V3_DUTCH_INPUT_TYPE_HASH = keccak256(V3_DUTCH_INPUT_TYPE); + bytes32 internal constant V3_DUTCH_INPUT_TYPE_HASH = + keccak256(abi.encodePacked(V3_DUTCH_INPUT_TYPE, NON_LINEAR_DECAY_TYPE)); bytes internal constant V3_DUTCH_OUTPUT_TYPE = abi.encodePacked( "V3DutchOutput(", "address token,", @@ -105,7 +106,8 @@ library V3DutchOrderLib { "uint256 minAmount,", "uint256 adjustmentPerGweiBaseFee)" ); - bytes32 internal constant V3_DUTCH_OUTPUT_TYPE_HASH = keccak256(V3_DUTCH_OUTPUT_TYPE); + bytes32 internal constant V3_DUTCH_OUTPUT_TYPE_HASH = + keccak256(abi.encodePacked(V3_DUTCH_OUTPUT_TYPE, NON_LINEAR_DECAY_TYPE)); bytes internal constant NON_LINEAR_DECAY_TYPE = abi.encodePacked("NonlinearDutchDecay(", "uint256 relativeBlocks,", "int256[] relativeAmounts)"); bytes32 internal constant NON_LINEAR_DECAY_TYPE_HASH = keccak256(NON_LINEAR_DECAY_TYPE); diff --git a/test/lib/EIP712.t.sol b/test/lib/EIP712.t.sol new file mode 100644 index 00000000..2b74e690 --- /dev/null +++ b/test/lib/EIP712.t.sol @@ -0,0 +1,46 @@ +import {Test} from "forge-std/Test.sol"; +import {NonlinearDutchDecay, V3DutchOrderLib, V3DutchOutput} from "../../src/lib/V3DutchOrderLib.sol"; + +contract EIP712Test is Test { + function test_NonlinearDutchDecayHash() public pure { + assertEq( + V3DutchOrderLib.NON_LINEAR_DECAY_TYPE_HASH, + hex"30c39ae6ecb284279579f99803ba5d7b54275a8a6a04180056b5031b8c19a01a" + ); + + int256[] memory amounts = new int256[](1); + amounts[0] = 1; + NonlinearDutchDecay memory curve = NonlinearDutchDecay(1, amounts); + assertEq(V3DutchOrderLib.hash(curve), hex"ad28931e960b684a49cdf1aca21bd966df5bac39996c5a0615c0a54f2f22a06f"); + } + + function test_V3DutchInputHash() public pure { + assertEq( + V3DutchOrderLib.V3_DUTCH_INPUT_TYPE_HASH, + hex"2cc4ccc271072d8b406616a16a6e9a3935dea10f0eb920f44737e1855ecc68eb" + ); + } + + function test_V3DutchOutputHash() public pure { + assertEq( + V3DutchOrderLib.V3_DUTCH_OUTPUT_TYPE_HASH, + hex"7fd857ffad1736e72f90e17c9d15cabe562b86b45c6e618ae0e7fa92c4a6fde9" + ); + + address token = address(0); + uint256 startAmount = 21; + int256[] memory amounts = new int256[](1); + amounts[0] = 1; + NonlinearDutchDecay memory curve = NonlinearDutchDecay(1, amounts); + address recipient = address(0); + uint256 minAmount = 20; + uint256 adjustmentPerGweiBaseFee = 0; + V3DutchOutput memory output = + V3DutchOutput(token, startAmount, curve, recipient, minAmount, adjustmentPerGweiBaseFee); + assertEq(V3DutchOrderLib.hash(output), hex"c57ac5e0436939ec593af412dde4a05d4972a0a8a56bbdb63ca7cd949c5326e2"); + } + + function test_OrderTypeHash() public pure { + assertEq(V3DutchOrderLib.ORDER_TYPE_HASH, hex"186c8af0344af94faab60c9dc413f68b8ca7aea1aded04a300c7fa35562ed1b7"); + } +} From 4a5269348324555175a57c00b8c4d7fc47c2dd56 Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Tue, 8 Oct 2024 05:16:57 -0500 Subject: [PATCH 2/9] docs: update cosigner info comments (#306) --- src/reactors/V3DutchOrderReactor.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reactors/V3DutchOrderReactor.sol b/src/reactors/V3DutchOrderReactor.sol index dd184237..41f63df6 100644 --- a/src/reactors/V3DutchOrderReactor.sol +++ b/src/reactors/V3DutchOrderReactor.sol @@ -14,7 +14,7 @@ import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; import {CosignerLib} from "../lib/CosignerLib.sol"; /// @notice Reactor for V3 dutch orders -/// @dev V3 orders must be cosigned by the specified cosigner to override starting block and value +/// @dev V3 orders must be cosigned by the specified cosigner to set the starting block and override the value /// @dev resolution behavior: /// - If cosignature is invalid or not from specified cosigner, revert /// - If inputAmount is 0, then use baseInput @@ -127,7 +127,7 @@ contract V3DutchOrderReactor is BaseReactor { /// @notice validate the dutch order fields /// - deadline must have not passed - /// - cosigner is valid if specified + /// - cosigner must always be provided and sign the cosignerData /// @dev Throws if the order is invalid function _validateOrder(bytes32 orderHash, V3DutchOrder memory order) internal view { if (order.info.deadline < block.timestamp) { From 7ef52bd2b1912654a8b07d3d25be6f8f70a24bbe Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Tue, 8 Oct 2024 07:27:21 -0500 Subject: [PATCH 3/9] docs: improved docs on locateCurvePosition & decay (#300) --- src/lib/NonlinearDutchDecayLib.sol | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/lib/NonlinearDutchDecayLib.sol b/src/lib/NonlinearDutchDecayLib.sol index b979a883..05d1a95e 100644 --- a/src/lib/NonlinearDutchDecayLib.sol +++ b/src/lib/NonlinearDutchDecayLib.sol @@ -17,11 +17,12 @@ library NonlinearDutchDecayLib { /// @notice thrown when the decay curve is invalid error InvalidDecayCurve(); - /// @notice locates the current position on the curve and calculates the decay - /// @param curve The curve to search - /// @param startAmount The absolute start amount - /// @param decayStartBlock The absolute start block of the decay + /// @notice Calculates the decayed amount based on the current block and the defined curve + /// @param curve The nonlinear decay curve definition + /// @param startAmount The initial amount at the start of the decay + /// @param decayStartBlock The absolute block number when the decay begins /// @dev Expects the relativeBlocks in curve to be strictly increasing + /// @return decayedAmount The amount after applying the decay, bounded by minAmount and maxAmount function decay( NonlinearDutchDecay memory curve, uint256 startAmount, @@ -48,13 +49,16 @@ library NonlinearDutchDecayLib { return startAmount.boundedSub(curveDelta, minAmount, maxAmount); } - /// @notice Locates the current position on the curve - /// @param curve The curve to search - /// @param currentRelativeBlock The current relative position - /// @return startPoint The relative block before the current position - /// @return endPoint The relative block after the current position - /// @return startAmount The relative amount before the current position - /// @return endAmount The relative amount after the current position + /// @notice Locates the current position on the decay curve based on the elapsed blocks + /// @param curve The nonlinear decay curve definition + /// @param currentRelativeBlock The number of blocks elapsed since decayStartBlock + /// @return startPoint The relative block number of the previous curve point + /// @return endPoint The relative block number of the next curve point + /// @return startAmount The relative change from initial amount at the previous curve point + /// @return endAmount The relative change from initial amount at the next curve point + /// @dev The returned amounts are changes relative to the initial startAmount, not absolute values + /// @dev If currentRelativeBlock is before the first curve point, startPoint and startAmount will be 0 + /// @dev If currentRelativeBlock is after the last curve point, both points will be the last curve point function locateCurvePosition(NonlinearDutchDecay memory curve, uint16 currentRelativeBlock) internal pure From 7d92c545f56bf17c12f2985983f7563fe5a7941c Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:13:33 -0500 Subject: [PATCH 4/9] docs: document integer overflow in MathExt (#307) --- src/lib/MathExt.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/MathExt.sol b/src/lib/MathExt.sol index 02a2a786..89bdf494 100644 --- a/src/lib/MathExt.sol +++ b/src/lib/MathExt.sol @@ -23,6 +23,7 @@ library MathExt { /// @param min The minimum bound for the result. /// @param max The maximum bound for the result. /// @return r The result of the bounded addition. + /// @dev This function reverts when `b == type(int256).min` due to integer overflow. function boundedAdd(uint256 a, int256 b, uint256 min, uint256 max) internal pure returns (uint256 r) { r = boundedSub(a, 0 - b, min, max); } @@ -33,6 +34,7 @@ library MathExt { /// @param min The minimum bound for the result. /// @param max The maximum bound for the result. /// @return r The result of the bounded subtraction. + /// @dev This function reverts when `b == type(int256).min` due to integer overflow. function boundedSub(uint256 a, int256 b, uint256 min, uint256 max) internal pure returns (uint256 r) { if (b < 0) { // If b is negative, add its absolute value to a From 8d9b8208796b83eb51bc1a706fa70134641fa773 Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:13:56 -0500 Subject: [PATCH 5/9] docs: typo in comments (#308) --- src/lib/V3DutchOrderLib.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/V3DutchOrderLib.sol b/src/lib/V3DutchOrderLib.sol index 8350cadd..5fb8612a 100644 --- a/src/lib/V3DutchOrderLib.sol +++ b/src/lib/V3DutchOrderLib.sol @@ -210,7 +210,7 @@ library V3DutchOrderLib { } /// @notice get the digest of the cosigner data - /// @param order the priorityOrder + /// @param order the V3DutchOrder /// @param orderHash the hash of the order function cosignerDigest(V3DutchOrder memory order, bytes32 orderHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked(orderHash, abi.encode(order.cosignerData))); From 3643ef38e10d13630a3887a771eabbd9df808fac Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:20:34 -0500 Subject: [PATCH 6/9] fix: omit bit masking before conversion (#311) --- .../Base-V3DutchOrder-BaseExecuteSingleWithFee.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap | 2 +- .../Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap | 2 +- ...V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap | 2 +- .../Base-V3DutchOrder-ExecuteBatchNativeOutput.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap | 2 +- .../Base-V3DutchOrder-ExecuteSingleNativeOutput.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap | 2 +- .forge-snapshots/V3-DutchDecay.snap | 2 +- .forge-snapshots/V3-DutchDecayFullyDecayed.snap | 2 +- .forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap | 2 +- .forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap | 2 +- .forge-snapshots/V3-LocateCurvePositionMulti.snap | 2 +- .forge-snapshots/V3-LocateCurvePositionSingle.snap | 2 +- .forge-snapshots/V3-MultiPointDutchDecay.snap | 2 +- src/types/Uint16Array.sol | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap b/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap index 54347403..09419f5e 100644 --- a/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap +++ b/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap @@ -1 +1 @@ -198780 \ No newline at end of file +200681 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap index 038dfe2d..a33857c2 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap @@ -1 +1 @@ -231116 \ No newline at end of file +234981 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap index 04587131..8d078b61 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap @@ -1 +1 @@ -244626 \ No newline at end of file +249505 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap index 3f03abfb..8e9dd714 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap @@ -1 +1 @@ -302041 \ No newline at end of file +307954 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap index 9e863299..21c6ea11 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap @@ -1 +1 @@ -224642 \ No newline at end of file +228508 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap index f90f0f91..19fb4c7f 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap @@ -1 +1 @@ -165165 \ No newline at end of file +167064 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap index 9b6d35ad..39c224b1 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap @@ -1 +1 @@ -150727 \ No newline at end of file +152626 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap index 692864e4..971c7be2 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap @@ -1 +1 @@ -174481 \ No newline at end of file +176375 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap b/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap index 5abcbe4d..5247d59e 100644 --- a/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap +++ b/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap @@ -1 +1 @@ -43785 \ No newline at end of file +45699 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap b/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap index 2b02fc3b..7c1a2689 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap @@ -1 +1 @@ -169089 \ No newline at end of file +170989 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap b/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap index 2d97ac44..5357aedb 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap @@ -1 +1 @@ -169170 \ No newline at end of file +171070 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap b/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap index b4dc2dd4..ebb55fb2 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap @@ -1 +1 @@ -169113 \ No newline at end of file +171013 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecay.snap b/.forge-snapshots/V3-DutchDecay.snap index 2b163bad..55abb6fe 100644 --- a/.forge-snapshots/V3-DutchDecay.snap +++ b/.forge-snapshots/V3-DutchDecay.snap @@ -1 +1 @@ -13179 \ No newline at end of file +13131 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayFullyDecayed.snap b/.forge-snapshots/V3-DutchDecayFullyDecayed.snap index e5e37b03..a2953231 100644 --- a/.forge-snapshots/V3-DutchDecayFullyDecayed.snap +++ b/.forge-snapshots/V3-DutchDecayFullyDecayed.snap @@ -1 +1 @@ -6677 \ No newline at end of file +6653 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap b/.forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap index 50d06af6..b8baf8da 100644 --- a/.forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap +++ b/.forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap @@ -1 +1 @@ -6365 \ No newline at end of file +6341 \ No newline at end of file diff --git a/.forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap b/.forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap index c1250b2e..90208a5f 100644 --- a/.forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap +++ b/.forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap @@ -1 +1 @@ -88354 \ No newline at end of file +87250 \ No newline at end of file diff --git a/.forge-snapshots/V3-LocateCurvePositionMulti.snap b/.forge-snapshots/V3-LocateCurvePositionMulti.snap index 73b08ba1..958c8b94 100644 --- a/.forge-snapshots/V3-LocateCurvePositionMulti.snap +++ b/.forge-snapshots/V3-LocateCurvePositionMulti.snap @@ -1 +1 @@ -20492 \ No newline at end of file +20330 \ No newline at end of file diff --git a/.forge-snapshots/V3-LocateCurvePositionSingle.snap b/.forge-snapshots/V3-LocateCurvePositionSingle.snap index 9726dc60..4a2277e6 100644 --- a/.forge-snapshots/V3-LocateCurvePositionSingle.snap +++ b/.forge-snapshots/V3-LocateCurvePositionSingle.snap @@ -1 +1 @@ -6860 \ No newline at end of file +6830 \ No newline at end of file diff --git a/.forge-snapshots/V3-MultiPointDutchDecay.snap b/.forge-snapshots/V3-MultiPointDutchDecay.snap index 81237bad..37c7ea87 100644 --- a/.forge-snapshots/V3-MultiPointDutchDecay.snap +++ b/.forge-snapshots/V3-MultiPointDutchDecay.snap @@ -1 +1 @@ -26242 \ No newline at end of file +26056 \ No newline at end of file diff --git a/src/types/Uint16Array.sol b/src/types/Uint16Array.sol index 0ecb75a7..61438038 100644 --- a/src/types/Uint16Array.sol +++ b/src/types/Uint16Array.sol @@ -37,7 +37,7 @@ library Uint16ArrayLibrary { } unchecked { uint256 shiftAmount = n * 16; - uint16 result = uint16((Uint16Array.unwrap(packedData) >> shiftAmount) & 0xFFFF); + uint16 result = uint16(Uint16Array.unwrap(packedData) >> shiftAmount); return result; } } From 8f91f4995b4dd402f7edb661b78e18cd88b1d0fe Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Wed, 9 Oct 2024 17:23:48 -0500 Subject: [PATCH 7/9] audit(11): Optimize gas in gas adjustment calculations (#303) * feat: gas optimization in gas adjustment calculations * style: forge fmt * chore: forge snapshots --- ...Base-V3DutchOrder-BaseExecuteSingleWithFee.snap | 2 +- .../Base-V3DutchOrder-ExecuteBatch.snap | 2 +- ...e-V3DutchOrder-ExecuteBatchMultipleOutputs.snap | 2 +- ...ExecuteBatchMultipleOutputsDifferentTokens.snap | 2 +- ...Base-V3DutchOrder-ExecuteBatchNativeOutput.snap | 2 +- .../Base-V3DutchOrder-ExecuteSingle.snap | 2 +- ...ase-V3DutchOrder-ExecuteSingleNativeOutput.snap | 2 +- .../Base-V3DutchOrder-ExecuteSingleValidation.snap | 2 +- .../Base-V3DutchOrder-RevertInvalidNonce.snap | 2 +- .../Base-V3DutchOrder-V3-ExclusiveFiller.snap | 2 +- .../Base-V3DutchOrder-V3-InputOverride.snap | 2 +- .../Base-V3DutchOrder-V3-OutputOverride.snap | 2 +- .forge-snapshots/V3-DutchDecayBounded.snap | 2 +- src/reactors/V3DutchOrderReactor.sol | 14 +++++++++----- 14 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap b/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap index 09419f5e..d0e11ef3 100644 --- a/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap +++ b/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap @@ -1 +1 @@ -200681 \ No newline at end of file +199162 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap index a33857c2..b686cada 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap @@ -1 +1 @@ -234981 \ No newline at end of file +231943 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap index 8d078b61..93bce628 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap @@ -1 +1 @@ -249505 \ No newline at end of file +245803 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap index 8e9dd714..34c24fb0 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap @@ -1 +1 @@ -307954 \ No newline at end of file +303588 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap index 21c6ea11..6b14a7ee 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap @@ -1 +1 @@ -228508 \ No newline at end of file +225470 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap index 19fb4c7f..ed4964dc 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap @@ -1 +1 @@ -167064 \ No newline at end of file +165545 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap index 39c224b1..74c548a4 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap @@ -1 +1 @@ -152626 \ No newline at end of file +151107 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap index 971c7be2..cc88aca3 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap @@ -1 +1 @@ -176375 \ No newline at end of file +174856 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap b/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap index 5247d59e..959c1f86 100644 --- a/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap +++ b/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap @@ -1 +1 @@ -45699 \ No newline at end of file +44180 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap b/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap index 7c1a2689..8ea13b83 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap @@ -1 +1 @@ -170989 \ No newline at end of file +169480 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap b/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap index 5357aedb..563a0ff4 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap @@ -1 +1 @@ -171070 \ No newline at end of file +169561 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap b/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap index ebb55fb2..8cac0069 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap @@ -1 +1 @@ -171013 \ No newline at end of file +169504 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayBounded.snap b/.forge-snapshots/V3-DutchDecayBounded.snap index 1f168c59..7862d759 100644 --- a/.forge-snapshots/V3-DutchDecayBounded.snap +++ b/.forge-snapshots/V3-DutchDecayBounded.snap @@ -1 +1 @@ -1199 \ No newline at end of file +1209 \ No newline at end of file diff --git a/src/reactors/V3DutchOrderReactor.sol b/src/reactors/V3DutchOrderReactor.sol index 41f63df6..c719baaa 100644 --- a/src/reactors/V3DutchOrderReactor.sol +++ b/src/reactors/V3DutchOrderReactor.sol @@ -113,15 +113,19 @@ contract V3DutchOrderReactor is BaseReactor { int256 gasDeltaGwei = block.basefee.sub(order.startingBaseFee); // Gas increase should increase input - int256 inputDelta = int256(order.baseInput.adjustmentPerGweiBaseFee) * gasDeltaGwei / 1 gwei; - order.baseInput.startAmount = order.baseInput.startAmount.boundedAdd(inputDelta, 0, order.baseInput.maxAmount); - + if (order.baseInput.adjustmentPerGweiBaseFee != 0) { + int256 inputDelta = int256(order.baseInput.adjustmentPerGweiBaseFee) * gasDeltaGwei / 1 gwei; + order.baseInput.startAmount = + order.baseInput.startAmount.boundedAdd(inputDelta, 0, order.baseInput.maxAmount); + } // Gas increase should decrease output uint256 outputsLength = order.baseOutputs.length; for (uint256 i = 0; i < outputsLength; i++) { V3DutchOutput memory output = order.baseOutputs[i]; - int256 outputDelta = int256(output.adjustmentPerGweiBaseFee) * gasDeltaGwei / 1 gwei; - output.startAmount = output.startAmount.boundedSub(outputDelta, output.minAmount, type(uint256).max); + if (output.adjustmentPerGweiBaseFee != 0) { + int256 outputDelta = int256(output.adjustmentPerGweiBaseFee) * gasDeltaGwei / 1 gwei; + output.startAmount = output.startAmount.boundedSub(outputDelta, output.minAmount, type(uint256).max); + } } } From f370eab6aa7ac3f72ab4b4641da102c82d71ed9f Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Wed, 9 Oct 2024 17:45:33 -0500 Subject: [PATCH 8/9] feat, test: handle long-term orders to properly decay (#304) * feat, test: handle long-term orders to properly decay * refactor: fuzz inputs match decay function params * style: forge fmt --- ...V3DutchOrder-BaseExecuteSingleWithFee.snap | 2 +- .../Base-V3DutchOrder-ExecuteBatch.snap | 2 +- ...utchOrder-ExecuteBatchMultipleOutputs.snap | 2 +- ...teBatchMultipleOutputsDifferentTokens.snap | 2 +- ...V3DutchOrder-ExecuteBatchNativeOutput.snap | 2 +- .../Base-V3DutchOrder-ExecuteSingle.snap | 2 +- ...3DutchOrder-ExecuteSingleNativeOutput.snap | 2 +- ...-V3DutchOrder-ExecuteSingleValidation.snap | 2 +- .../Base-V3DutchOrder-RevertInvalidNonce.snap | 2 +- .../Base-V3DutchOrder-V3-ExclusiveFiller.snap | 2 +- .../Base-V3DutchOrder-V3-InputOverride.snap | 2 +- .../Base-V3DutchOrder-V3-OutputOverride.snap | 2 +- .forge-snapshots/V3-DutchDecay.snap | 2 +- .forge-snapshots/V3-DutchDecayBounded.snap | 2 +- .../V3-DutchDecayFullyDecayed.snap | 2 +- .../V3-DutchDecayFullyDecayedNegative.snap | 2 +- .forge-snapshots/V3-DutchDecayNegative.snap | 2 +- .forge-snapshots/V3-DutchDecayNoDecayYet.snap | 2 +- .../V3-DutchDecayNoDecayYetNegative.snap | 2 +- .forge-snapshots/V3-DutchDecayRange.snap | 2 +- .../V3-ExtendedMultiPointDutchDecay.snap | 2 +- .forge-snapshots/V3-MultiPointDutchDecay.snap | 2 +- src/lib/NonlinearDutchDecayLib.sol | 6 ++- test/lib/NonLinearDutchDecayLib.t.sol | 41 +++++++++++++++++++ 24 files changed, 67 insertions(+), 24 deletions(-) diff --git a/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap b/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap index d0e11ef3..8d568a0e 100644 --- a/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap +++ b/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap @@ -1 +1 @@ -199162 \ No newline at end of file +199140 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap index b686cada..8435ecfc 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap @@ -1 +1 @@ -231943 \ No newline at end of file +231899 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap index 93bce628..94184e2e 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap @@ -1 +1 @@ -245803 \ No newline at end of file +245748 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap index 34c24fb0..6c03d83b 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap @@ -1 +1 @@ -303588 \ No newline at end of file +303522 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap index 6b14a7ee..04a1e7b7 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap @@ -1 +1 @@ -225470 \ No newline at end of file +225426 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap index ed4964dc..5d053c0e 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap @@ -1 +1 @@ -165545 \ No newline at end of file +165523 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap index 74c548a4..588d4376 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap @@ -1 +1 @@ -151107 \ No newline at end of file +151085 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap index cc88aca3..08e791ca 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap @@ -1 +1 @@ -174856 \ No newline at end of file +174834 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap b/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap index 959c1f86..55167125 100644 --- a/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap +++ b/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap @@ -1 +1 @@ -44180 \ No newline at end of file +44158 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap b/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap index 8ea13b83..2d877d64 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap @@ -1 +1 @@ -169480 \ No newline at end of file +169458 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap b/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap index 563a0ff4..dcd33d51 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap @@ -1 +1 @@ -169561 \ No newline at end of file +169539 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap b/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap index 8cac0069..d107b689 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap @@ -1 +1 @@ -169504 \ No newline at end of file +169482 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecay.snap b/.forge-snapshots/V3-DutchDecay.snap index 55abb6fe..284a734f 100644 --- a/.forge-snapshots/V3-DutchDecay.snap +++ b/.forge-snapshots/V3-DutchDecay.snap @@ -1 +1 @@ -13131 \ No newline at end of file +13371 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayBounded.snap b/.forge-snapshots/V3-DutchDecayBounded.snap index 7862d759..29001eb5 100644 --- a/.forge-snapshots/V3-DutchDecayBounded.snap +++ b/.forge-snapshots/V3-DutchDecayBounded.snap @@ -1 +1 @@ -1209 \ No newline at end of file +1206 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayFullyDecayed.snap b/.forge-snapshots/V3-DutchDecayFullyDecayed.snap index a2953231..e2b27312 100644 --- a/.forge-snapshots/V3-DutchDecayFullyDecayed.snap +++ b/.forge-snapshots/V3-DutchDecayFullyDecayed.snap @@ -1 +1 @@ -6653 \ No newline at end of file +6779 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap b/.forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap index b8baf8da..67e488ea 100644 --- a/.forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap +++ b/.forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap @@ -1 +1 @@ -6341 \ No newline at end of file +6467 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayNegative.snap b/.forge-snapshots/V3-DutchDecayNegative.snap index 11b9a892..34201494 100644 --- a/.forge-snapshots/V3-DutchDecayNegative.snap +++ b/.forge-snapshots/V3-DutchDecayNegative.snap @@ -1 +1 @@ -1271 \ No newline at end of file +1265 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayNoDecayYet.snap b/.forge-snapshots/V3-DutchDecayNoDecayYet.snap index 9b08816d..222192ce 100644 --- a/.forge-snapshots/V3-DutchDecayNoDecayYet.snap +++ b/.forge-snapshots/V3-DutchDecayNoDecayYet.snap @@ -1 +1 @@ -4703 \ No newline at end of file +4697 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayNoDecayYetNegative.snap b/.forge-snapshots/V3-DutchDecayNoDecayYetNegative.snap index 9b08816d..222192ce 100644 --- a/.forge-snapshots/V3-DutchDecayNoDecayYetNegative.snap +++ b/.forge-snapshots/V3-DutchDecayNoDecayYetNegative.snap @@ -1 +1 @@ -4703 \ No newline at end of file +4697 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayRange.snap b/.forge-snapshots/V3-DutchDecayRange.snap index 11b9a892..34201494 100644 --- a/.forge-snapshots/V3-DutchDecayRange.snap +++ b/.forge-snapshots/V3-DutchDecayRange.snap @@ -1 +1 @@ -1271 \ No newline at end of file +1265 \ No newline at end of file diff --git a/.forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap b/.forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap index 90208a5f..6dffa512 100644 --- a/.forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap +++ b/.forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap @@ -1 +1 @@ -87250 \ No newline at end of file +88450 \ No newline at end of file diff --git a/.forge-snapshots/V3-MultiPointDutchDecay.snap b/.forge-snapshots/V3-MultiPointDutchDecay.snap index 37c7ea87..1a263175 100644 --- a/.forge-snapshots/V3-MultiPointDutchDecay.snap +++ b/.forge-snapshots/V3-MultiPointDutchDecay.snap @@ -1 +1 @@ -26056 \ No newline at end of file +26539 \ No newline at end of file diff --git a/src/lib/NonlinearDutchDecayLib.sol b/src/lib/NonlinearDutchDecayLib.sol index 05d1a95e..bdeaa5f1 100644 --- a/src/lib/NonlinearDutchDecayLib.sol +++ b/src/lib/NonlinearDutchDecayLib.sol @@ -5,6 +5,7 @@ import {OutputToken, InputToken} from "../base/ReactorStructs.sol"; import {V3DutchOutput, V3DutchInput, NonlinearDutchDecay} from "../lib/V3DutchOrderLib.sol"; import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol"; import {MathExt} from "./MathExt.sol"; +import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; import {Uint16ArrayLibrary, Uint16Array, fromUnderlying} from "../types/Uint16Array.sol"; import {DutchDecayLib} from "./DutchDecayLib.sol"; @@ -39,8 +40,9 @@ library NonlinearDutchDecayLib { if (decayStartBlock >= block.number || curve.relativeAmounts.length == 0) { return startAmount.bound(minAmount, maxAmount); } - - uint16 blockDelta = uint16(block.number - decayStartBlock); + // If the blockDelta is larger than type(uint16).max, a downcast overflow will occur + // We prevent this by capping the blockDelta to type(uint16).max to express a full decay + uint16 blockDelta = uint16(Math.min(block.number - decayStartBlock, type(uint16).max)); (uint16 startPoint, uint16 endPoint, int256 relStartAmount, int256 relEndAmount) = locateCurvePosition(curve, blockDelta); // get decay of only the relative amounts diff --git a/test/lib/NonLinearDutchDecayLib.t.sol b/test/lib/NonLinearDutchDecayLib.t.sol index c4217418..8fa6c522 100644 --- a/test/lib/NonLinearDutchDecayLib.t.sol +++ b/test/lib/NonLinearDutchDecayLib.t.sol @@ -8,6 +8,7 @@ import {DutchDecayLib} from "../../src/lib/DutchDecayLib.sol"; import {NonlinearDutchDecayLib} from "../../src/lib/NonlinearDutchDecayLib.sol"; import {V3DutchOutput, V3DutchInput, NonlinearDutchDecay} from "../../src/lib/V3DutchOrderLib.sol"; import {Uint16Array, toUint256} from "../../src/types/Uint16Array.sol"; +import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; import {ArrayBuilder} from "../util/ArrayBuilder.sol"; import {CurveBuilder} from "../util/CurveBuilder.sol"; @@ -474,4 +475,44 @@ contract NonlinearDutchDecayLibTest is Test, GasSnapshot { vm.expectRevert(NonlinearDutchDecayLib.InvalidDecayCurve.selector); mockNonlinearDutchDecayLibContract.decay(curve, startAmount, decayStartBlock, 1 ether, 1 ether); } + + function testFuzzDutchDecayBeyondUint16Max( + uint16 lastValidBlock, // For curve + uint256 decayAmountFuzz, // For curve + // decay(curve, startAmount, decayStartBlock, minAmount, maxAmount); + uint256 startAmount, + uint256 decayStartBlock, + uint256 minAmount, + uint256 maxAmount, + uint256 currentBlock + ) public { + vm.assume(decayStartBlock < type(uint256).max - type(uint16).max); + vm.assume(lastValidBlock > 0); + vm.assume(startAmount > 0 && startAmount < uint256(type(int256).max)); + vm.assume(maxAmount >= startAmount); + minAmount = bound(minAmount, 0, startAmount); + // bound only takes uint256, so we need to limit decayAmountFuzz to int256.max + // because we cast it to int256 in the decay function + decayAmountFuzz = bound(decayAmountFuzz, minAmount, startAmount); + + // Testing that we get a fully decayed curve instead of overflowed mistake + // This will happen when the block delta is larger than type(uint16).max + vm.assume(currentBlock > decayStartBlock + type(uint16).max); + + uint16[] memory blocks = new uint16[](1); + blocks[0] = lastValidBlock; + + int256[] memory decayAmounts = new int256[](1); + decayAmounts[0] = int256(decayAmountFuzz); + + NonlinearDutchDecay memory curve = CurveBuilder.multiPointCurve(blocks, decayAmounts); + + vm.roll(currentBlock); + uint256 decayed = NonlinearDutchDecayLib.decay(curve, startAmount, decayStartBlock, minAmount, maxAmount); + assertEq( + decayed, + Math.max(startAmount - decayAmountFuzz, minAmount), + "Should be fully decayed for block delta beyond uint16.max" + ); + } } From 8f35a85e7d04a1bc757c42b7dbc6888689bceb83 Mon Sep 17 00:00:00 2001 From: Alan Wu <60207036+alanhwu@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:52:24 -0500 Subject: [PATCH 9/9] feat: Use chain id for replay protection (#309) * feat: use chain id in cosignerDigest for replay protection * chore: forge snapshots --- .../Base-V3DutchOrder-BaseExecuteSingleWithFee.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap | 2 +- .../Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap | 2 +- ...DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap | 2 +- .../Base-V3DutchOrder-ExecuteBatchNativeOutput.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap | 2 +- .../Base-V3DutchOrder-ExecuteSingleNativeOutput.snap | 2 +- .../Base-V3DutchOrder-ExecuteSingleValidation.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap | 2 +- .forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap | 2 +- .forge-snapshots/V3-DutchDecayBounded.snap | 2 +- src/lib/V3DutchOrderLib.sol | 4 ++-- test/reactors/V3DutchOrderReactor.t.sol | 4 ++-- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap b/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap index 8d568a0e..5cd8344c 100644 --- a/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap +++ b/.forge-snapshots/Base-V3DutchOrder-BaseExecuteSingleWithFee.snap @@ -1 +1 @@ -199140 \ No newline at end of file +199172 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap index 8435ecfc..26009a86 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap @@ -1 +1 @@ -231899 \ No newline at end of file +231968 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap index 94184e2e..9540249d 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputs.snap @@ -1 +1 @@ -245748 \ No newline at end of file +245818 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap index 6c03d83b..432d427d 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchMultipleOutputsDifferentTokens.snap @@ -1 +1 @@ -303522 \ No newline at end of file +303592 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap index 04a1e7b7..e97b81f9 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteBatchNativeOutput.snap @@ -1 +1 @@ -225426 \ No newline at end of file +225494 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap index 5d053c0e..9cee8b71 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap @@ -1 +1 @@ -165523 \ No newline at end of file +165555 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap index 588d4376..7ae7e611 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleNativeOutput.snap @@ -1 +1 @@ -151085 \ No newline at end of file +151117 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap index 08e791ca..188a54c0 100644 --- a/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap +++ b/.forge-snapshots/Base-V3DutchOrder-ExecuteSingleValidation.snap @@ -1 +1 @@ -174834 \ No newline at end of file +174866 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap b/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap index 55167125..e5308bcc 100644 --- a/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap +++ b/.forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap @@ -1 +1 @@ -44158 \ No newline at end of file +44191 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap b/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap index 2d877d64..78251840 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap @@ -1 +1 @@ -169458 \ No newline at end of file +169490 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap b/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap index dcd33d51..c5c65d5c 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap @@ -1 +1 @@ -169539 \ No newline at end of file +169571 \ No newline at end of file diff --git a/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap b/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap index d107b689..f1a4bb72 100644 --- a/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap +++ b/.forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap @@ -1 +1 @@ -169482 \ No newline at end of file +169514 \ No newline at end of file diff --git a/.forge-snapshots/V3-DutchDecayBounded.snap b/.forge-snapshots/V3-DutchDecayBounded.snap index 29001eb5..77e48ce7 100644 --- a/.forge-snapshots/V3-DutchDecayBounded.snap +++ b/.forge-snapshots/V3-DutchDecayBounded.snap @@ -1 +1 @@ -1206 \ No newline at end of file +1193 \ No newline at end of file diff --git a/src/lib/V3DutchOrderLib.sol b/src/lib/V3DutchOrderLib.sol index 5fb8612a..38cef7e4 100644 --- a/src/lib/V3DutchOrderLib.sol +++ b/src/lib/V3DutchOrderLib.sol @@ -212,7 +212,7 @@ library V3DutchOrderLib { /// @notice get the digest of the cosigner data /// @param order the V3DutchOrder /// @param orderHash the hash of the order - function cosignerDigest(V3DutchOrder memory order, bytes32 orderHash) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(orderHash, abi.encode(order.cosignerData))); + function cosignerDigest(V3DutchOrder memory order, bytes32 orderHash) internal view returns (bytes32) { + return keccak256(abi.encodePacked(orderHash, block.chainid, abi.encode(order.cosignerData))); } } diff --git a/test/reactors/V3DutchOrderReactor.t.sol b/test/reactors/V3DutchOrderReactor.t.sol index fe4420e4..aee42438 100644 --- a/test/reactors/V3DutchOrderReactor.t.sol +++ b/test/reactors/V3DutchOrderReactor.t.sol @@ -1451,8 +1451,8 @@ contract V3DutchOrderTest is PermitSignature, DeployPermit2, BaseReactorTest { (order,) = createAndSignDutchOrder(request); } - function cosignOrder(bytes32 orderHash, CosignerData memory cosignerData) private pure returns (bytes memory sig) { - bytes32 msgHash = keccak256(abi.encodePacked(orderHash, abi.encode(cosignerData))); + function cosignOrder(bytes32 orderHash, CosignerData memory cosignerData) private view returns (bytes memory sig) { + bytes32 msgHash = keccak256(abi.encodePacked(orderHash, block.chainid, abi.encode(cosignerData))); (uint8 v, bytes32 r, bytes32 s) = vm.sign(cosignerPrivateKey, msgHash); sig = bytes.concat(r, s, bytes1(v)); }