Skip to content

Commit

Permalink
feat, test: handle long-term orders to properly decay (#304)
Browse files Browse the repository at this point in the history
* feat, test: handle long-term orders to properly decay

* refactor: fuzz inputs match decay function params

* style: forge fmt
  • Loading branch information
alanhwu authored Oct 9, 2024
1 parent 8f91f49 commit f370eab
Show file tree
Hide file tree
Showing 24 changed files with 67 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
199162
199140
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
231943
231899
Original file line number Diff line number Diff line change
@@ -1 +1 @@
245803
245748
Original file line number Diff line number Diff line change
@@ -1 +1 @@
303588
303522
Original file line number Diff line number Diff line change
@@ -1 +1 @@
225470
225426
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
165545
165523
Original file line number Diff line number Diff line change
@@ -1 +1 @@
151107
151085
Original file line number Diff line number Diff line change
@@ -1 +1 @@
174856
174834
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
44180
44158
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
169480
169458
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
169561
169539
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
169504
169482
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
13131
13371
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayBounded.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1209
1206
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayFullyDecayed.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6653
6779
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6341
6467
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayNegative.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1271
1265
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayNoDecayYet.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4703
4697
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayNoDecayYetNegative.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4703
4697
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayRange.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1271
1265
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
87250
88450
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-MultiPointDutchDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
26056
26539
6 changes: 4 additions & 2 deletions src/lib/NonlinearDutchDecayLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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
Expand Down
41 changes: 41 additions & 0 deletions test/lib/NonLinearDutchDecayLib.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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"
);
}
}

0 comments on commit f370eab

Please sign in to comment.