Skip to content

Commit

Permalink
Reactor tests pt1, refactor tests, fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
codyborn committed Aug 31, 2024
1 parent 98473ae commit 29f6ed9
Show file tree
Hide file tree
Showing 36 changed files with 1,059 additions and 537 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
192981
1 change: 1 addition & 0 deletions .forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
219434
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
231444
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
287371
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
212953
1 change: 1 addition & 0 deletions .forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
159369
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
144927
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
168675
1 change: 1 addition & 0 deletions .forge-snapshots/Base-V3DutchOrder-InputOverride.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
163131
1 change: 1 addition & 0 deletions .forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
37963
1 change: 1 addition & 0 deletions .forge-snapshots/Base-V3DutchOrder-V3-ExclusiveFiller.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
163306
1 change: 1 addition & 0 deletions .forge-snapshots/Base-V3DutchOrder-V3-InputOverride.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
163383
1 change: 1 addition & 0 deletions .forge-snapshots/Base-V3DutchOrder-V3-OutputOverride.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
163332
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayBounded.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1070
5778
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayFullyDecayed.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
14834
14782
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
14686
14634
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayNoDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4721
5457
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
219678
219186
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-LocateCurvePositionMulti.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
24913
24798
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-LocateCurvePositionSingle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8855
8820
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-MultiPointDutchDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
52157
51976
6 changes: 5 additions & 1 deletion src/lib/ExclusivityLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ library ExclusivityLib {
/// @dev if the order has no exclusivity, always returns true
/// @dev if the order has active exclusivity and the current filler is the exclusive address, returns true
/// @dev if the order has active exclusivity and the current filler is not the exclusive address, returns false
function hasFillingRights(address exclusive, uint256 exclusivityEnd, uint256 currentPosition) internal view returns (bool) {
function hasFillingRights(address exclusive, uint256 exclusivityEnd, uint256 currentPosition)
internal
view
returns (bool)
{
return exclusive == address(0) || currentPosition > exclusivityEnd || exclusive == msg.sender;
}
}
31 changes: 15 additions & 16 deletions src/lib/V3DutchDecayLib.sol → src/lib/NonlinearDutchDecayLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.0;

import {OutputToken, InputToken} from "../base/ReactorStructs.sol";
import {V3DutchOutput, V3DutchInput, V3Decay} from "../lib/V3DutchOrderLib.sol";
import {V3DutchOutput, V3DutchInput, NonlinearDutchDecay} from "../lib/V3DutchOrderLib.sol";
import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol";
import {sub} from "./MathExt.sol";
import {Uint16Array, fromUnderlying} from "../types/Uint16Array.sol";
Expand All @@ -11,22 +11,21 @@ import {Uint16Array, fromUnderlying} from "../types/Uint16Array.sol";
error InvalidDecayCurve();

/// @notice helpers for handling non-linear dutch order objects
library V3DutchDecayLib {

library NonlinearDutchDecayLib {
using FixedPointMathLib for uint256;
using {sub} for uint256;

/// @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
function decay(V3Decay memory curve, uint256 startAmount, uint256 decayStartBlock)
function decay(NonlinearDutchDecay memory curve, uint256 startAmount, uint256 decayStartBlock)
internal
view
returns (uint256 decayedAmount)
{
// mismatch of relativeAmounts and relativeBlocks
if(curve.relativeAmounts.length > 16) {
if (curve.relativeAmounts.length > 16) {
revert InvalidDecayCurve();
}

Expand All @@ -38,31 +37,31 @@ library V3DutchDecayLib {
uint16 blockDelta = uint16(block.number - decayStartBlock);
// Special case for when we need to use the decayStartBlock (0)
if (relativeBlocks.getElement(0) > blockDelta) {
return linearDecay(0, relativeBlocks.getElement(0), blockDelta, startAmount, startAmount.sub(curve.relativeAmounts[0]));
return linearDecay(
0, relativeBlocks.getElement(0), blockDelta, startAmount, startAmount.sub(curve.relativeAmounts[0])
);
}
// the current pos is within or after the curve
uint16 prev;
uint16 next;
(prev, next) = locateCurvePosition(curve, blockDelta);
(uint16 prev, uint16 next) = locateCurvePosition(curve, blockDelta);
uint256 lastAmount = startAmount.sub(curve.relativeAmounts[prev]);
uint256 nextAmount = startAmount.sub(curve.relativeAmounts[next]);
return linearDecay(relativeBlocks.getElement(prev), relativeBlocks.getElement(next), blockDelta, lastAmount, nextAmount);
return linearDecay(
relativeBlocks.getElement(prev), relativeBlocks.getElement(next), blockDelta, lastAmount, nextAmount
);
}

/// @notice Locates the current position on the curve using a binary search
/// @param curve The curve to search
/// @param currentRelativeBlock The current relative position
/// @return prev The relative block before the current position
/// @return next The relative block after the current position
function locateCurvePosition(V3Decay memory curve, uint16 currentRelativeBlock)
function locateCurvePosition(NonlinearDutchDecay memory curve, uint16 currentRelativeBlock)
internal
pure
returns (uint16 prev, uint16 next)
{
Uint16Array relativeBlocks = fromUnderlying(curve.relativeBlocks);
prev = 0;
next = 0;
while(next < curve.relativeAmounts.length) {
while (next < curve.relativeAmounts.length) {
if (relativeBlocks.getElement(next) >= currentRelativeBlock) {
return (prev, next);
}
Expand Down Expand Up @@ -108,7 +107,7 @@ library V3DutchDecayLib {
view
returns (OutputToken memory result)
{
uint256 decayedOutput = V3DutchDecayLib.decay(output.curve, output.startAmount, decayStartBlock);
uint256 decayedOutput = NonlinearDutchDecayLib.decay(output.curve, output.startAmount, decayStartBlock);
result = OutputToken(output.token, decayedOutput, output.recipient);
}

Expand Down Expand Up @@ -139,7 +138,7 @@ library V3DutchDecayLib {
view
returns (InputToken memory result)
{
uint256 decayedInput = V3DutchDecayLib.decay(input.curve, input.startAmount, decayStartBlock);
uint256 decayedInput = NonlinearDutchDecayLib.decay(input.curve, input.startAmount, decayStartBlock);
result = InputToken(input.token, decayedInput, input.maxAmount);
}
}
12 changes: 6 additions & 6 deletions src/lib/V3DutchOrderLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct V3DutchOrder {

/// @dev The changes in tokens (positive or negative) to subtract from the start amount
/// @dev The relativeBlocks should be strictly increasing
struct V3Decay {
struct NonlinearDutchDecay {
// 16 uint16 values packed
// Can represent curves with points 2^16 blocks into the future
uint256 relativeBlocks;
Expand All @@ -50,7 +50,7 @@ struct V3DutchInput {
// The amount of tokens at the starting block
uint256 startAmount;
// The amount of tokens at the each future block
V3Decay curve;
NonlinearDutchDecay curve;
// The max amount of the curve
uint256 maxAmount;
}
Expand All @@ -62,7 +62,7 @@ struct V3DutchOutput {
// The amount of tokens at the start of the time period
uint256 startAmount;
// The amount of tokens at the each future block
V3Decay curve;
NonlinearDutchDecay curve;
// The address who must receive the tokens to satisfy the order
address recipient;
}
Expand All @@ -79,11 +79,11 @@ library V3DutchOrderLib {
"V3DutchOutput[] baseOutputs)"
);
bytes internal constant NON_LINEAR_DUTCH_OUTPUT_TYPE = abi.encodePacked(
"V3DutchOutput(", "address token,", "uint256 startAmount,", "V3Decay curve,", "address recipient)"
"V3DutchOutput(", "address token,", "uint256 startAmount,", "NonlinearDutchDecay curve,", "address recipient)"
);
bytes32 internal constant NON_LINEAR_DUTCH_OUTPUT_TYPE_HASH = keccak256(NON_LINEAR_DUTCH_OUTPUT_TYPE);
bytes internal constant NON_LINEAR_DECAY_TYPE =
abi.encodePacked("V3Decay(", "uint256 relativeBlocks,", "int256[] relativeAmounts)");
abi.encodePacked("NonlinearDutchDecay(", "uint256 relativeBlocks,", "int256[] relativeAmounts)");
bytes32 internal constant NON_LINEAR_DECAY_TYPE_HASH = keccak256(NON_LINEAR_DECAY_TYPE);

bytes internal constant ORDER_TYPE = abi.encodePacked(
Expand All @@ -103,7 +103,7 @@ library V3DutchOrderLib {
)
);

function hash(V3Decay memory curve) internal pure returns (bytes32) {
function hash(NonlinearDutchDecay memory curve) internal pure returns (bytes32) {
return keccak256(
abi.encode(
NON_LINEAR_DECAY_TYPE_HASH, curve.relativeBlocks, keccak256(abi.encodePacked(curve.relativeAmounts))
Expand Down
14 changes: 4 additions & 10 deletions src/reactors/V3DutchOrderReactor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@ import {BaseReactor} from "./BaseReactor.sol";
import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
import {Permit2Lib} from "../lib/Permit2Lib.sol";
import {ExclusivityLib} from "../lib/ExclusivityLib.sol";
import {V3DutchDecayLib} from "../lib/V3DutchDecayLib.sol";
import {
V3DutchOrderLib,
V3DutchOrder,
CosignerData,
V3DutchOutput,
V3DutchInput
} from "../lib/V3DutchOrderLib.sol";
import {NonlinearDutchDecayLib} from "../lib/NonlinearDutchDecayLib.sol";
import {V3DutchOrderLib, V3DutchOrder, CosignerData, V3DutchOutput, V3DutchInput} from "../lib/V3DutchOrderLib.sol";
import {SignedOrder, ResolvedOrder} from "../base/ReactorStructs.sol";

/// @notice Reactor for non-linear dutch orders
Expand All @@ -27,8 +21,8 @@ import {SignedOrder, ResolvedOrder} from "../base/ReactorStructs.sol";
contract V3DutchOrderReactor is BaseReactor {
using Permit2Lib for ResolvedOrder;
using V3DutchOrderLib for V3DutchOrder;
using V3DutchDecayLib for V3DutchOutput[];
using V3DutchDecayLib for V3DutchInput;
using NonlinearDutchDecayLib for V3DutchOutput[];
using NonlinearDutchDecayLib for V3DutchInput;
using ExclusivityLib for ResolvedOrder;

/// @notice thrown when an order's deadline is passed
Expand Down
4 changes: 3 additions & 1 deletion src/types/Uint16Array.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ pragma solidity ^0.8.0;

/// @dev An uint16 array of max 16 values packed into a single uint256
type Uint16Array is uint256;

using Uint16ArrayLibrary for Uint16Array global;

error IndexOutOfBounds();
error InvalidArrLength();

Expand Down Expand Up @@ -41,4 +43,4 @@ library Uint16ArrayLibrary {
return result;
}
}
}
}
30 changes: 19 additions & 11 deletions test/lib/ExclusivityLib.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ contract ExclusivityLibTest is Test {
assertEq(exclusivity.hasFillingRights(exclusive, block.timestamp + 1, block.timestamp), true);
}

function testExclusivityFail(address caller, address exclusive, uint256 nowTime, uint256 exclusiveEnd)
public
{
function testExclusivityFail(address caller, address exclusive, uint256 nowTime, uint256 exclusiveEnd) public {
vm.assume(nowTime <= exclusiveEnd);
vm.assume(caller != exclusive);
vm.assume(exclusive != address(0));
Expand Down Expand Up @@ -76,7 +74,9 @@ contract ExclusivityLibTest is Test {
assertEq(handled.outputs[0].recipient, recipient);
}

function testHandleExclusiveOverrideTimestampPassNoExclusivity(address caller, uint256 overrideAmt, uint128 amount) public {
function testHandleExclusiveOverrideTimestampPassNoExclusivity(address caller, uint256 overrideAmt, uint128 amount)
public
{
vm.assume(overrideAmt < 10000);
ResolvedOrder memory order;
order.outputs = OutputsBuilder.single(token1, amount, recipient);
Expand All @@ -88,7 +88,9 @@ contract ExclusivityLibTest is Test {
assertEq(handled.outputs[0].recipient, recipient);
}

function testHandleExclusiveOverrideBlockPassNoExclusivity(address caller, uint256 overrideAmt, uint128 amount) public {
function testHandleExclusiveOverrideBlockPassNoExclusivity(address caller, uint256 overrideAmt, uint128 amount)
public
{
vm.assume(overrideAmt < 10000);
ResolvedOrder memory order;
order.outputs = OutputsBuilder.single(token1, amount, recipient);
Expand Down Expand Up @@ -206,9 +208,12 @@ contract ExclusivityLibTest is Test {
assertEq(handled.outputs[0].recipient, recipient);
}

function testHandleExclusiveOverrideTimestampApplied(address caller, address exclusive, uint256 overrideAmt, uint128 amount)
public
{
function testHandleExclusiveOverrideTimestampApplied(
address caller,
address exclusive,
uint256 overrideAmt,
uint128 amount
) public {
vm.assume(caller != exclusive);
vm.assume(exclusive != address(0));
vm.assume(overrideAmt < 10000 && overrideAmt > 0);
Expand All @@ -222,9 +227,12 @@ contract ExclusivityLibTest is Test {
assertEq(handled.outputs[0].recipient, recipient);
}

function testHandleExclusiveOverrideBlockApplied(address caller, address exclusive, uint256 overrideAmt, uint128 amount)
public
{
function testHandleExclusiveOverrideBlockApplied(
address caller,
address exclusive,
uint256 overrideAmt,
uint128 amount
) public {
vm.assume(caller != exclusive);
vm.assume(exclusive != address(0));
vm.assume(overrideAmt < 10000 && overrideAmt > 0);
Expand Down
4 changes: 2 additions & 2 deletions test/lib/MathExt.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
pragma solidity ^0.8.0;

import {Test} from "forge-std/Test.sol";
import {V3DutchDecayLib} from "../../src/lib/V3DutchDecayLib.sol";
import {V3DutchOutput, V3DutchInput, V3Decay} from "../../src/lib/V3DutchOrderLib.sol";
import {NonlinearDutchDecayLib} from "../../src/lib/NonlinearDutchDecayLib.sol";
import {V3DutchOutput, V3DutchInput, NonlinearDutchDecay} from "../../src/lib/V3DutchOrderLib.sol";
import {sub, NegativeUint} from "../../src/lib/MathExt.sol";
import {ArrayBuilder} from "../util/ArrayBuilder.sol";

Expand Down
Loading

0 comments on commit 29f6ed9

Please sign in to comment.