Skip to content

Commit

Permalink
Merge branch 'main' into audit-v3-12
Browse files Browse the repository at this point in the history
alanhwu committed Oct 9, 2024
2 parents 7525238 + 8f91f49 commit e7dfb37
Showing 26 changed files with 100 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
198736
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 @@
231028
231899
Original file line number Diff line number Diff line change
@@ -1 +1 @@
244516
245748
Original file line number Diff line number Diff line change
@@ -1 +1 @@
301909
303522
Original file line number Diff line number Diff line change
@@ -1 +1 @@
224554
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 @@
165121
165523
Original file line number Diff line number Diff line change
@@ -1 +1 @@
150683
151085
Original file line number Diff line number Diff line change
@@ -1 +1 @@
174437
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 @@
43741
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 @@
169045
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 @@
169126
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 @@
169069
169482
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
13419
13371
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayBounded.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1193
1206
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayFullyDecayed.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6803
6779
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-DutchDecayFullyDecayedNegative.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6491
6467
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-ExtendedMultiPointDutchDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
89554
88450
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-LocateCurvePositionMulti.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20492
20330
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-LocateCurvePositionSingle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6860
6830
2 changes: 1 addition & 1 deletion .forge-snapshots/V3-MultiPointDutchDecay.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
26725
26539
2 changes: 2 additions & 0 deletions src/lib/MathExt.sol
Original file line number Diff line number Diff line change
@@ -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
26 changes: 15 additions & 11 deletions src/lib/NonlinearDutchDecayLib.sol
Original file line number Diff line number Diff line change
@@ -18,11 +18,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,
@@ -50,13 +51,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
8 changes: 5 additions & 3 deletions src/lib/V3DutchOrderLib.sol
Original file line number Diff line number Diff line change
@@ -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);
@@ -208,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)));
18 changes: 11 additions & 7 deletions src/reactors/V3DutchOrderReactor.sol
Original file line number Diff line number Diff line change
@@ -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
@@ -113,21 +113,25 @@ 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);
}
}
}

/// @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) {
2 changes: 1 addition & 1 deletion src/types/Uint16Array.sol
Original file line number Diff line number Diff line change
@@ -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;
}
}
46 changes: 46 additions & 0 deletions test/lib/EIP712.t.sol
Original file line number Diff line number Diff line change
@@ -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");
}
}

0 comments on commit e7dfb37

Please sign in to comment.