Skip to content

Commit

Permalink
refactor: use solmate for rounding, test wei instead of gwei
Browse files Browse the repository at this point in the history
  • Loading branch information
alanhwu committed Oct 3, 2024
1 parent 8dce531 commit 5e8716f
Show file tree
Hide file tree
Showing 14 changed files with 49 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
198780
198680
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-ExecuteBatch.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
231116
230916
Original file line number Diff line number Diff line change
@@ -1 +1 @@
244626
244376
Original file line number Diff line number Diff line change
@@ -1 +1 @@
302041
301741
Original file line number Diff line number Diff line change
@@ -1 +1 @@
224642
224442
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-ExecuteSingle.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
165165
165065
Original file line number Diff line number Diff line change
@@ -1 +1 @@
150727
150627
Original file line number Diff line number Diff line change
@@ -1 +1 @@
174481
174381
2 changes: 1 addition & 1 deletion .forge-snapshots/Base-V3DutchOrder-RevertInvalidNonce.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
43785
43685
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 @@
169089
168989
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 @@
169170
169070
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 @@
169113
169013
27 changes: 17 additions & 10 deletions src/reactors/V3DutchOrderReactor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {FixedPointMathLib} from "solmate/src/utils/FixedPointMathLib.sol";
import {MathExt} from "../lib/MathExt.sol";
import {Math} from "openzeppelin-contracts/utils/math/Math.sol";
import {CosignerLib} from "../lib/CosignerLib.sol";
import {SafeCast} from "openzeppelin-contracts/utils/math/SafeCast.sol";

/// @notice Reactor for V3 dutch orders
/// @dev V3 orders must be cosigned by the specified cosigner to override starting block and value
Expand Down Expand Up @@ -109,26 +110,32 @@ contract V3DutchOrderReactor is BaseReactor {
}

function _updateWithGasAdjustment(V3DutchOrder memory order) internal view {
// positive means an increase in gas
int256 gasDeltaGwei = block.basefee.sub(order.startingBaseFee);
// Positive means an increase in gas
int256 gasDeltaWei = block.basefee.sub(order.startingBaseFee);

// Gas increase should increase input (round up when positive, down when negative)
int256 inputDelta = gasDeltaGwei >= 0
? (int256(order.baseInput.adjustmentPerGweiBaseFee) * gasDeltaGwei + 1 gwei - 1) / 1 gwei
: (int256(order.baseInput.adjustmentPerGweiBaseFee) * gasDeltaGwei) / 1 gwei;
// Round in favor of swapper
int256 inputDelta = _computeDelta(order.baseInput.adjustmentPerGweiBaseFee, gasDeltaWei);
order.baseInput.startAmount = order.baseInput.startAmount.boundedAdd(inputDelta, 0, order.baseInput.maxAmount);

// Gas increase should decrease output (round down when positive, up when negative)
uint256 outputsLength = order.baseOutputs.length;
for (uint256 i = 0; i < outputsLength; i++) {
V3DutchOutput memory output = order.baseOutputs[i];
int256 outputDelta = gasDeltaGwei >= 0
? (int256(output.adjustmentPerGweiBaseFee) * gasDeltaGwei) / 1 gwei
: (int256(output.adjustmentPerGweiBaseFee) * gasDeltaGwei - 1 gwei + 1) / 1 gwei;
// Round in favor of swapper
int256 outputDelta = _computeDelta(output.adjustmentPerGweiBaseFee, gasDeltaWei);
output.startAmount = output.startAmount.boundedSub(outputDelta, output.minAmount, type(uint256).max);
}
}

function _computeDelta(uint256 adjustmentPerGweiBaseFee, int256 gasDeltaWei) internal pure returns (int256) {
if (gasDeltaWei >= 0) {
// Gas increase: round adjustment down to decrease amount added to input or subtracted from output
return int256(adjustmentPerGweiBaseFee.mulDivDown(uint256(gasDeltaWei), 1 gwei));
} else {
// Gas decrease: round adjustment up to increase amount added to output or subtracted from input
return -int256(adjustmentPerGweiBaseFee.mulDivUp(SafeCast.toUint256(-gasDeltaWei), 1 gwei));
}
}

/// @notice validate the dutch order fields
/// - deadline must have not passed
/// - cosigner is valid if specified
Expand Down
38 changes: 20 additions & 18 deletions test/reactors/V3DutchOrderReactor.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1406,47 +1406,49 @@ contract V3DutchOrderTest is PermitSignature, DeployPermit2, BaseReactorTest {
vm.roll(currentBlock);
vm.fee(1 gwei);

// Order with 0.8 gwei gas adjustments
// Order with 1 wei gas adjustments
SignedOrder memory order = generateOrder(
TestDutchOrderSpec({
currentBlock: currentBlock,
startBlock: currentBlock,
deadline: currentBlock + 21,
input: V3DutchInput(tokenIn, 100 ether, CurveBuilder.emptyCurve(), 101 ether, 0.8 gwei),
input: V3DutchInput(tokenIn, 1000, CurveBuilder.emptyCurve(), 1100, 1),
outputs: OutputsBuilder.singleV3Dutch(
V3DutchOutput(address(tokenOut), 100 ether, CurveBuilder.emptyCurve(), address(0), 99 ether, 0.8 gwei)
V3DutchOutput(address(tokenOut), 1000, CurveBuilder.emptyCurve(), address(0), 900, 1)
)
})
);

// Test gas increase
vm.fee(2 gwei);
vm.fee(1.5 gwei);
ResolvedOrder memory resolvedOrder = quoter.quote(order.order, order.sig);
assertEq(resolvedOrder.input.amount, 100 ether + 0.8 gwei, "Input should round up for positive gas change");
assertEq(resolvedOrder.outputs[0].amount, 100 ether - 0.8 gwei, "Output should round down for positive gas change");
// The gas adjusted input would be 1000.5, which should round down to 1000
assertEq(resolvedOrder.input.amount, 1000, "Input should round down");
// The gas adjusted output would be 999.5, which should round up to 1000
assertEq(resolvedOrder.outputs[0].amount, 1000, "Output should round up");

// Test gas decrease
vm.fee(0.5 gwei);
resolvedOrder = quoter.quote(order.order, order.sig);
assertEq(resolvedOrder.input.amount, 100 ether - 0.4 gwei, "Input should round down for negative gas change");
assertEq(resolvedOrder.outputs[0].amount, 100 ether + 0.4 gwei, "Output should round up for negative gas change");

// Test gas half
vm.fee(0.5 gwei);
resolvedOrder = quoter.quote(order.order, order.sig);
assertEq(resolvedOrder.input.amount, 100 ether - 0.4 gwei, "Input should round down for gas halving change");
assertEq(resolvedOrder.outputs[0].amount, 100 ether + 0.4 gwei, "Output should round up for exact gas halving change");
// The gas adjusted input would be 999.5, which should round down to 999
assertEq(resolvedOrder.input.amount, 999, "Input should round down");
// The gas adjusted output would be 1000.5, which should round up to 1001
assertEq(resolvedOrder.outputs[0].amount, 1001, "Output should round up");

// Test smaller gas changes
vm.fee(1.1 gwei);
resolvedOrder = quoter.quote(order.order, order.sig);
assertEq(resolvedOrder.input.amount, 100 ether + 0.08 gwei, "Input should handle small positive gas changes");
assertEq(resolvedOrder.outputs[0].amount, 100 ether - 0.08 gwei, "Output should handle small positive gas changes");
// The gas adjusted input would be 1000.1, which should round down to 1000
assertEq(resolvedOrder.input.amount, 1000, "Input should round down");
// The gas adjusted output would be 999.9, which should round up to 1000
assertEq(resolvedOrder.outputs[0].amount, 1000, "Output should round up");

vm.fee(0.9 gwei);
resolvedOrder = quoter.quote(order.order, order.sig);
assertEq(resolvedOrder.input.amount, 100 ether - 0.08 gwei, "Input should handle small negative gas changes");
assertEq(resolvedOrder.outputs[0].amount, 100 ether + 0.08 gwei, "Output should handle small negative gas changes");
// The gas adjusted input would be 999.9, which should round down to 999
assertEq(resolvedOrder.input.amount, 999, "Input should round down");
// The gas adjusted output would be 1000.1, which should round up to 1001
assertEq(resolvedOrder.outputs[0].amount, 1001, "Output should round up");
}

/* Test helpers */
Expand Down

0 comments on commit 5e8716f

Please sign in to comment.