SwapOrder.inverted

This commit is contained in:
tim
2024-10-27 23:52:21 -04:00
parent 1d118931cf
commit 64f1645764
11 changed files with 94 additions and 74 deletions

View File

@@ -189,11 +189,11 @@ library OrderLib {
_prepTrancheStatus(tranche,status.trancheStatus[t],startTime); _prepTrancheStatus(tranche,status.trancheStatus[t],startTime);
if (tranche.minIsRatio || tranche.maxIsRatio) if (tranche.minIsRatio || tranche.maxIsRatio)
needStartPrice = true; needStartPrice = true;
// require(!tranche.marketOrder || !tranche.minIntercept.isNegative(), 'NSL'); // negative slippage require(!tranche.marketOrder || !tranche.minLine.intercept.isNegative(), 'NSL'); // negative slippage
} }
// console2.log('fee/oco'); // console2.log('fee/oco');
if (needStartPrice) if (needStartPrice)
status.startPrice = router.protectedPrice(order.route.exchange, order.tokenIn, order.tokenOut, order.route.fee); status.startPrice = router.protectedPrice(order.route.exchange, order.tokenIn, order.tokenOut, order.route.fee, order.inverted);
} }
@@ -219,6 +219,7 @@ library OrderLib {
SwapOrderStatus storage status = self.orders[orderIndex]; SwapOrderStatus storage status = self.orders[orderIndex];
if (_isCanceled(self, orderIndex)) if (_isCanceled(self, orderIndex))
revert('NO'); // Not Open revert('NO'); // Not Open
SwapOrder storage order = status.order;
Tranche storage tranche = status.order.tranches[trancheIndex]; Tranche storage tranche = status.order.tranches[trancheIndex];
TrancheStatus storage tStatus = status.trancheStatus[trancheIndex]; TrancheStatus storage tStatus = status.trancheStatus[trancheIndex];
@@ -236,8 +237,8 @@ library OrderLib {
// market order slippage control: we overload minLine.intercept to store slippage value // market order slippage control: we overload minLine.intercept to store slippage value
if( tranche.marketOrder && !tranche.minLine.intercept.isZero() ) { if( tranche.marketOrder && !tranche.minLine.intercept.isZero() ) {
// console2.log('slippage'); // console2.log('slippage');
uint256 protectedPrice = router.protectedPrice(status.order.route.exchange, status.order.tokenIn, uint256 protectedPrice = router.protectedPrice(order.route.exchange, order.tokenIn,
status.order.tokenOut, status.order.route.fee); order.tokenOut, order.route.fee, order.inverted);
// minIntercept is interpreted as the slippage ratio // minIntercept is interpreted as the slippage ratio
uint256 slippage = uint256(tranche.minLine.intercept.toFixed(96)); uint256 slippage = uint256(tranche.minLine.intercept.toFixed(96));
v.limit = protectedPrice * 2**96 / (2**96+slippage); v.limit = protectedPrice * 2**96 / (2**96+slippage);
@@ -247,27 +248,29 @@ library OrderLib {
} }
// line constraints // line constraints
// price math is done in the linspace determined by order.inverted.
else { else {
v.price = 0; v.price = 0;
// check min line // check min line
if( tranche.minLine.isEnabled() ) { if( tranche.minLine.isEnabled() ) {
v.price = router.rawPrice(status.order.route.exchange, status.order.tokenIn, v.price = router.rawPrice(order.route.exchange, order.tokenIn,
status.order.tokenOut, status.order.route.fee); order.tokenOut, order.route.fee, order.inverted);
// console2.log('price'); // console2.log('price', v.price);
// console2.log(v.price); uint256 minPrice = tranche.minIsRatio ?
v.limit = tranche.minIsRatio ?
tranche.minLine.ratioPrice(status.startTime, status.startPrice) : tranche.minLine.ratioPrice(status.startTime, status.startPrice) :
tranche.minLine.priceNow(); tranche.minLine.priceNow();
// console2.log('min line limit', v.limit); // console2.log('min line limit', v.limit);
// console2.log('price', v.price); // console2.log('price', v.price);
require( v.price > v.limit, 'LL' ); require( v.price > minPrice, 'LL' );
if ((order.tokenIn < order.tokenOut) != order.inverted)
v.limit = minPrice;
} }
// check max line // check max line
if( tranche.maxLine.isEnabled()) { if( tranche.maxLine.isEnabled()) {
// price may have been already initialized by the min line // price may have been already initialized by the min line
if( v.price == 0 ) { // don't look it up a second time if we already have it. if( v.price == 0 ) { // don't look it up a second time if we already have it.
v.price = router.rawPrice(status.order.route.exchange, status.order.tokenIn, v.price = router.rawPrice(order.route.exchange, order.tokenIn,
status.order.tokenOut, status.order.route.fee); order.tokenOut, order.route.fee, order.inverted);
// console2.log('price'); // console2.log('price');
// console2.log(v.price); // console2.log(v.price);
} }
@@ -277,11 +280,13 @@ library OrderLib {
// console2.log('max line limit'); // console2.log('max line limit');
// console2.log(maxPrice); // console2.log(maxPrice);
require( v.price <= maxPrice, 'LU' ); require( v.price <= maxPrice, 'LU' );
if ((order.tokenIn > order.tokenOut) != order.inverted)
v.limit = maxPrice;
} }
} }
// compute size // compute size
v.trancheAmount = status.order.amount * tranche.fraction / MAX_FRACTION; // the most this tranche could do v.trancheAmount = order.amount * tranche.fraction / MAX_FRACTION; // the most this tranche could do
v.amount = v.trancheAmount - tStatus.filled; // minus tranche fills v.amount = v.trancheAmount - tStatus.filled; // minus tranche fills
if (tranche.rateLimitFraction != 0) { if (tranche.rateLimitFraction != 0) {
// rate limit sizing // rate limit sizing
@@ -290,36 +295,35 @@ library OrderLib {
v.amount = v.limitedAmount; v.amount = v.limitedAmount;
} }
// order amount remaining // order amount remaining
v.remaining = status.order.amount - status.filled; v.remaining = order.amount - status.filled;
if (v.amount > v.remaining) // not more than the order's overall remaining amount if (v.amount > v.remaining) // not more than the order's overall remaining amount
v.amount = v.remaining; v.amount = v.remaining;
require( v.amount >= status.order.minFillAmount, 'TF' ); require( v.amount >= order.minFillAmount, 'TF' );
address recipient = status.order.outputDirectlyToOwner ? owner : address(this); address recipient = order.outputDirectlyToOwner ? owner : address(this);
IERC20 outToken = IERC20(status.order.tokenOut); IERC20 outToken = IERC20(order.tokenOut);
// this variable is only needed for calculating the amount to forward to a conditional order, so we set it to 0 otherwise // this variable is only needed for calculating the amount to forward to a conditional order, so we set it to 0 otherwise
uint256 startingTokenOutBalance = status.order.conditionalOrder == NO_CONDITIONAL_ORDER ? 0 : outToken.balanceOf(address(this)); uint256 startingTokenOutBalance = order.conditionalOrder == NO_CONDITIONAL_ORDER ? 0 : outToken.balanceOf(address(this));
// //
// Order has been approved. Send to router for swap execution. // Order has been approved. Send to router for swap execution.
// //
// console2.log('router request:'); // console2.log('router request:');
// console2.log(status.order.tokenIn); // console2.log(order.tokenIn);
// console2.log(status.order.tokenOut); // console2.log(order.tokenOut);
// console2.log(recipient); // console2.log(recipient);
// console2.log(v.amount); // console2.log(v.amount);
// console2.log(status.order.minFillAmount); // console2.log(order.minFillAmount);
// console2.log(status.order.amountIsInput); // console2.log(order.amountIsInput);
// console2.log(v.limit); // console2.log(v.limit);
// console2.log(status.order.route.fee); // console2.log(order.route.fee);
IRouter.SwapParams memory swapParams = IRouter.SwapParams( IRouter.SwapParams memory swapParams = IRouter.SwapParams(
status.order.tokenIn, status.order.tokenOut, recipient, order.route.exchange, order.tokenIn, order.tokenOut, recipient,
v.amount, status.order.minFillAmount, status.order.amountIsInput, v.amount, order.minFillAmount, order.amountIsInput,
v.limit, status.order.route.fee); order.inverted, v.limit, order.route.fee);
// DELEGATECALL // DELEGATECALL
(bool success, bytes memory result) = address(router).delegatecall( (bool success, bytes memory result) = address(router).delegatecall(
abi.encodeWithSelector(IRouter.swap.selector, status.order.route.exchange, swapParams) abi.encodeWithSelector(IRouter.swap.selector, swapParams));
);
if (!success) { if (!success) {
if (result.length > 0) { // if there was a reason given, forward it if (result.length > 0) { // if there was a reason given, forward it
assembly ("memory-safe") { assembly ("memory-safe") {
@@ -333,8 +337,10 @@ library OrderLib {
// delegatecall succeeded // delegatecall succeeded
(v.amountIn, amountOut) = abi.decode(result, (uint256, uint256)); (v.amountIn, amountOut) = abi.decode(result, (uint256, uint256));
// console2.log('swapped');
// Update filled amounts // Update filled amounts
v.amount = status.order.amountIsInput ? v.amountIn : amountOut; v.amount = order.amountIsInput ? v.amountIn : amountOut;
status.filled += v.amount; status.filled += v.amount;
tStatus.filled += v.amount; tStatus.filled += v.amount;
@@ -348,24 +354,25 @@ library OrderLib {
v.fillFee = amountOut * status.fillFeeHalfBps / 20_000; v.fillFee = amountOut * status.fillFeeHalfBps / 20_000;
outToken.transfer(feeManager.fillFeeAccount(), v.fillFee); outToken.transfer(feeManager.fillFeeAccount(), v.fillFee);
emit DexorderSwapFilled(orderIndex, trancheIndex, v.amountIn, amountOut, v.fillFee, emit DexorderSwapFilled(orderIndex, trancheIndex, v.amountIn, amountOut, v.fillFee, tStatus.activationTime);
tStatus.activationTime);
// Conditional order placement // Conditional order placement
// Fees for conditional orders are taken up-front by the VaultImpl and are not charged here. // Fees for conditional orders are taken up-front by the VaultImpl and are not charged here.
if (status.order.conditionalOrder != NO_CONDITIONAL_ORDER) { if (order.conditionalOrder != NO_CONDITIONAL_ORDER) {
// the conditional order index will have been converted to an absolute index during placement // the conditional order index will have been converted to an absolute index during placement
SwapOrder memory condi = self.orders[status.order.conditionalOrder].order; SwapOrder memory condi = self.orders[order.conditionalOrder].order;
// the amount forwarded will be different than amountOut due to our fee and possible token transfer taxes // the amount forwarded will be different than amountOut due to our fee and possible token transfer taxes
condi.amount = outToken.balanceOf(address(this)) - startingTokenOutBalance; condi.amount = outToken.balanceOf(address(this)) - startingTokenOutBalance;
// fillFee is preserved // fillFee is preserved
uint64 condiOrderIndex = _createOrder(self, condi, status.fillFeeHalfBps, NO_OCO_INDEX, router, status.order.conditionalOrder); uint64 condiOrderIndex = _createOrder(
self, condi, status.fillFeeHalfBps,
NO_OCO_INDEX, router, order.conditionalOrder);
emit DexorderSwapPlaced(condiOrderIndex, 1, 0, 0); // zero fees emit DexorderSwapPlaced(condiOrderIndex, 1, 0, 0); // zero fees
} }
// Check order completion and OCO canceling // Check order completion and OCO canceling
uint256 remaining = status.order.amount - status.filled; uint256 remaining = order.amount - status.filled;
if( remaining < status.order.minFillAmount ) { if( remaining < order.minFillAmount ) {
// we already get fill events so completion may be inferred without an extra Completion event // we already get fill events so completion may be inferred without an extra Completion event
if( status.ocoGroup != NO_OCO_INDEX) if( status.ocoGroup != NO_OCO_INDEX)
_cancelOco(self, status.ocoGroup); _cancelOco(self, status.ocoGroup);

View File

@@ -49,6 +49,13 @@ struct SwapOrder {
uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed
bool amountIsInput; // whether amount is an in or out amount bool amountIsInput; // whether amount is an in or out amount
bool outputDirectlyToOwner; // whether the swap proceeds should go to the vault, or directly to the vault owner bool outputDirectlyToOwner; // whether the swap proceeds should go to the vault, or directly to the vault owner
// Tranche prices are expressed as either inToken/outToken or outToken/inToken depending on this `inverted` flag.
// A line in one space is a curve in the other, so the specification of e.g. WETH/USDC or USDC/WETH is essential.
// The "natural" ordering of inverted=false follows Uniswap: the lower-address token is the base currency and the
// higher-address token is the quote.
bool inverted;
uint64 conditionalOrder; // use NO_CONDITIONAL_ORDER for normal orders. If the high bit is set, the order number is relative to the currently placed group of orders. e.g. `CONDITIONAL_ORDER_IN_CURRENT_GROUP & 2` refers to the third item in the order group currently being placed. uint64 conditionalOrder; // use NO_CONDITIONAL_ORDER for normal orders. If the high bit is set, the order number is relative to the currently placed group of orders. e.g. `CONDITIONAL_ORDER_IN_CURRENT_GROUP & 2` refers to the third item in the order group currently being placed.
Tranche[] tranches; // see Tranche below Tranche[] tranches; // see Tranche below
} }
@@ -87,8 +94,9 @@ struct Tranche {
uint32 endTime; // use DISTANT_FUTURE to effectively disable uint32 endTime; // use DISTANT_FUTURE to effectively disable
// If intercept and slope are both 0, the line is disabled // If intercept and slope are both 0, the line is disabled
// Prices are always in terms of outputToken as the quote currency: the output amount per input amount. This is // Prices are expressed as either inToken/outToken or outToken/inToken depending on the order `inverted` flag.
// equivalent to saying all orders are viewed as sells relative to the price. // A line in one space is a curve in the other, so the specification of e.g. WETH/USDC or USDC/WETH is critical
// The minLine is equivalent to a traditional limit order constraint, except this limit line can be diagonal. // The minLine is equivalent to a traditional limit order constraint, except this limit line can be diagonal.
Line minLine; Line minLine;
// The maxLine will be relatively unused, since it represents a boundry on TOO GOOD of a price. // The maxLine will be relatively unused, since it represents a boundry on TOO GOOD of a price.
@@ -117,4 +125,4 @@ struct OcoGroup {
OcoMode mode; OcoMode mode;
uint64 startIndex; // starting orderIndex of the group uint64 startIndex; // starting orderIndex of the group
uint8 num; // number of orders in the group uint8 num; // number of orders in the group
} }

View File

@@ -16,25 +16,25 @@ contract Router is IRouter, UniswapV3Swapper {
} }
function rawPrice(Exchange exchange, address tokenIn, address tokenOut, uint24 maxFee) external view function rawPrice(Exchange exchange, address tokenIn, address tokenOut, uint24 maxFee, bool inverted) external view
returns (uint256) { returns (uint256) {
if (exchange == Exchange.UniswapV3) if (exchange == Exchange.UniswapV3)
return _univ3_rawPrice(tokenIn, tokenOut, maxFee); return _univ3_rawPrice(tokenIn, tokenOut, maxFee, inverted);
revert('UR'); revert('UR'); // Unknown Route
} }
function protectedPrice(Exchange exchange, address tokenIn, address tokenOut, uint24 maxFee) external view function protectedPrice(Exchange exchange, address tokenIn, address tokenOut, uint24 maxFee, bool inverted) external view
returns (uint256) { returns (uint256) {
if (exchange == Exchange.UniswapV3) if (exchange == Exchange.UniswapV3)
return _univ3_protectedPrice(tokenIn, tokenOut, maxFee); return _univ3_protectedPrice(tokenIn, tokenOut, maxFee, inverted);
revert('UR'); revert('UR'); // Unknown Route
} }
function swap( Exchange exchange, SwapParams memory params ) external function swap( SwapParams memory params ) external
returns (uint256 amountIn, uint256 amountOut) { returns (uint256 amountIn, uint256 amountOut) {
if (exchange == Exchange.UniswapV3) if (params.exchange == Exchange.UniswapV3)
return _univ3_swap(params); return _univ3_swap(params);
revert('UR'); revert('UR'); // Unknown Route
} }
} }

View File

@@ -28,21 +28,22 @@ contract UniswapV3Swapper {
oracleSeconds = oracleSeconds_; oracleSeconds = oracleSeconds_;
} }
function _univ3_rawPrice(address tokenIn, address tokenOut, uint24 maxFee) internal view function _univ3_rawPrice(address tokenIn, address tokenOut, uint24 maxFee, bool inverted) internal view
returns (uint256 price) { returns (uint256 price) {
(IUniswapV3Pool pool, bool inverted) = UniswapV3.getPool(factory, tokenIn, tokenOut, maxFee); IUniswapV3Pool pool = UniswapV3.getPool(factory, tokenIn, tokenOut, maxFee);
(uint160 sqrtPriceX96,,,,,,) = pool.slot0(); (uint160 sqrtPriceX96,,,,,,) = pool.slot0();
return Util.sqrtToPrice(sqrtPriceX96, inverted); return Util.sqrtToPrice(sqrtPriceX96, inverted);
} }
// Returns the stabilized (oracle) price // Returns the stabilized (oracle) price
function _univ3_protectedPrice(address tokenIn, address tokenOut, uint24 maxFee) internal view function _univ3_protectedPrice(address tokenIn, address tokenOut, uint24 maxFee, bool inverted) internal view
returns (uint256) returns (uint256)
{ {
// console2.log('oracle'); // console2.log('oracle');
// console2.log(oracleSeconds); // console2.log(oracleSeconds);
IUniswapV3Pool pool = UniswapV3.getPool(factory, tokenIn, tokenOut, maxFee);
uint160 sqrtPriceX96;
if (oracleSeconds!=0){ if (oracleSeconds!=0){
(IUniswapV3Pool pool, bool inverted) = UniswapV3.getPool(factory, tokenIn, tokenOut, maxFee);
uint32[] memory secondsAgos = new uint32[](2); uint32[] memory secondsAgos = new uint32[](2);
secondsAgos[0] = oracleSeconds; secondsAgos[0] = oracleSeconds;
secondsAgos[1] = 0; secondsAgos[1] = 0;
@@ -53,7 +54,7 @@ contract UniswapV3Swapper {
if (delta < 0 && (delta % secsI != 0)) if (delta < 0 && (delta % secsI != 0))
mean--; mean--;
// use Uniswap's tick-to-sqrt-price because it's verified // use Uniswap's tick-to-sqrt-price because it's verified
uint160 sqrtPriceX96 = TickMath.getSqrtRatioAtTick(mean); sqrtPriceX96 = TickMath.getSqrtRatioAtTick(mean);
return Util.sqrtToPrice(sqrtPriceX96, inverted); return Util.sqrtToPrice(sqrtPriceX96, inverted);
} }
catch Error( string memory /*reason*/ ) { catch Error( string memory /*reason*/ ) {
@@ -61,20 +62,22 @@ contract UniswapV3Swapper {
// console2.log('oracle broken'); // console2.log('oracle broken');
} }
} }
return _univ3_rawPrice(tokenIn, tokenOut, maxFee); // no oracle available. use the raw pool price.
(sqrtPriceX96,,,,,,) = pool.slot0();
return Util.sqrtToPrice(sqrtPriceX96, inverted);
} }
function _univ3_swap(IRouter.SwapParams memory params) internal function _univ3_swap(IRouter.SwapParams memory params) internal
returns (uint256 amountIn, uint256 amountOut) { returns (uint256 amountIn, uint256 amountOut) {
if( params.limitPriceX96 != 0 ) { if( params.limitPriceX96 != 0 ) {
bool inverted = params.tokenIn > params.tokenOut; // convert to output/input which is what the _univ3_* methods expect
if (inverted) { bool inputInverted = params.tokenIn > params.tokenOut;
if (params.inverted!=inputInverted) {
// console2.log('inverting params.limitPriceX96'); // console2.log('inverting params.limitPriceX96');
// console2.log(params.limitPriceX96); // console2.log(params.limitPriceX96);
params.limitPriceX96 = 2**96 * 2**96 / params.limitPriceX96; params.limitPriceX96 = Util.invertX96(params.limitPriceX96);
} }
// console2.log('params.limitPriceX96'); // console2.log('params.limitPriceX96', params.limitPriceX96);
// console2.log(params.limitPriceX96);
} }
if (params.amountIsInput) if (params.amountIsInput)
(amountIn, amountOut) = _univ3_swapExactInput(params); (amountIn, amountOut) = _univ3_swapExactInput(params);

View File

@@ -10,10 +10,9 @@ import {IWETH9} from "../../lib_uniswap/v3-periphery/contracts/interfaces/extern
library UniswapV3 { library UniswapV3 {
function getPool( IUniswapV3Factory factory, address tokenA, address tokenB, uint24 fee) internal pure function getPool( IUniswapV3Factory factory, address tokenA, address tokenB, uint24 fee) internal pure
returns (IUniswapV3Pool pool, bool inverted) { returns (IUniswapV3Pool) {
PoolAddress.PoolKey memory key = PoolAddress.getPoolKey(tokenA, tokenB, fee); PoolAddress.PoolKey memory key = PoolAddress.getPoolKey(tokenA, tokenB, fee);
pool = IUniswapV3Pool(PoolAddress.computeAddress(address(factory), key)); return IUniswapV3Pool(PoolAddress.computeAddress(address(factory), key));
inverted = tokenA > tokenB;
} }
} }

View File

@@ -21,7 +21,7 @@ import {UniswapV3Arbitrum} from "./UniswapV3.sol";
contract VaultImpl is IVaultImpl, VaultStorage { contract VaultImpl is IVaultImpl, VaultStorage {
uint256 constant public version = 1; uint256 constant public version = 2;
IFeeManager public immutable feeManager; IFeeManager public immutable feeManager;
IRouter private immutable router; IRouter private immutable router;

View File

@@ -6,25 +6,27 @@ import "../core/OrderSpec.sol";
interface IRouter { interface IRouter {
// Returns the current price of the pool for comparison with limit lines. // Returns the current price of the pool for comparison with limit lines.
function rawPrice(Exchange exchange, address tokenIn, address tokenOut, uint24 maxFee) external view function rawPrice(Exchange exchange, address tokenIn, address tokenOut, uint24 maxFee, bool inverted) external view
returns (uint256); returns (uint256);
// Returns the oracle price, with protections against fast moving price changes (typically used in comparisons to slippage price) // Returns the oracle price, with protections against fast moving price changes (typically used in comparisons to slippage price)
function protectedPrice(Exchange exchange, address tokenIn, address tokenOut, uint24 maxFee) external view function protectedPrice(Exchange exchange, address tokenIn, address tokenOut, uint24 maxFee, bool inverted) external view
returns (uint256); returns (uint256);
struct SwapParams { struct SwapParams {
Exchange exchange;
address tokenIn; address tokenIn;
address tokenOut; address tokenOut;
address recipient; address recipient;
uint256 amount; uint256 amount;
uint256 minAmount; uint256 minAmount;
bool amountIsInput; bool amountIsInput;
bool inverted;
uint256 limitPriceX96; uint256 limitPriceX96;
uint24 maxFee; uint24 maxFee;
} }
function swap( Exchange exchange, SwapParams memory params ) external function swap( SwapParams memory params ) external
returns (uint256 amountIn, uint256 amountOut); returns (uint256 amountIn, uint256 amountOut);
} }

View File

@@ -6,7 +6,7 @@ import "@forge-std/console2.sol";
library VaultAddress { library VaultAddress {
// keccak-256 hash of the Vault's bytecode (not the deployed bytecode but the initialization bytecode) // keccak-256 hash of the Vault's bytecode (not the deployed bytecode but the initialization bytecode)
bytes32 public constant VAULT_INIT_CODE_HASH = 0x8b1347850b0b1f2e05548c065af07c78f2c0617f70a2915b3cb7e0ba1bd20630; bytes32 public constant VAULT_INIT_CODE_HASH = 0xda672cdca096de00f3fed8150430564c059a59ad30cb2c824902097e25cd8b3a;
// the contract being constructed must not have any constructor arguments or the determinism will be broken. // the contract being constructed must not have any constructor arguments or the determinism will be broken.
// instead, use a callback to get construction arguments // instead, use a callback to get construction arguments

View File

@@ -39,7 +39,7 @@ contract TestCancelOrder is MockEnv, Test {
SwapOrder memory order = SwapOrder( SwapOrder memory order = SwapOrder(
0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9, 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1, 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9, 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1,
Route(Exchange.UniswapV3, 500), amount, amount/100, true, false, Route(Exchange.UniswapV3, 500), amount, amount/100, true, false, false,
NO_CONDITIONAL_ORDER, tranches NO_CONDITIONAL_ORDER, tranches
); );
vault.placeDexorder(order); vault.placeDexorder(order);

View File

@@ -67,17 +67,18 @@ contract TestIEEE754 is Test {
Item(float.wrap(0x80200000), 128, int256(uint256(int256(-0x1)))), // smallest negative is subnormal Item(float.wrap(0x80200000), 128, int256(uint256(int256(-0x1)))), // smallest negative is subnormal
Item(float.wrap(0x7effffff), 128, int256(uint256(0x7fffff8000000000000000000000000000000000000000000000000000000000))), // largest positive Item(float.wrap(0x7effffff), 128, int256(uint256(0x7fffff8000000000000000000000000000000000000000000000000000000000))), // largest positive
Item(float.wrap(0xff7fffff), 128, -int256(uint256(0xffffff0000000000000000000000000000000000000000000000000000000000))), // largest negative Item(float.wrap(0xff7fffff), 128, -int256(uint256(0xffffff0000000000000000000000000000000000000000000000000000000000))), // largest negative
Item(float.wrap(0x7f7fffff), 120, int256(uint256(0xffffff0000000000000000000000000000000000000000000000000000000000))) Item(float.wrap(0x7f7fffff), 128, int256(uint256(0xffffff0000000000000000000000000000000000000000000000000000000000)))
]; ];
for (uint i=0; i<items.length; i++) { for (uint i=0; i<items.length; i++) {
console2.log("index", i);
console2.log("exp: %x", uint256(items[i].fixedPoint)); console2.log("exp: %x", uint256(items[i].fixedPoint));
int256 fixedPoint = IEEE754.toFixed( int256 fixedPoint = IEEE754.toFixed(
items[i].floatingPoint, items[i].fixedBits items[i].floatingPoint, items[i].fixedBits
); );
console2.log("got: %x", uint256(fixedPoint)); console2.log("got: %x", uint256(fixedPoint));
console2.log(IEEE754.isPositive(items[i].floatingPoint)?' positive':' negative'); console2.log(IEEE754.isPositive(items[i].floatingPoint)?' positive':' negative');
require(items[i].fixedPoint == fixedPoint); require(items[i].fixedPoint == fixedPoint, 'conversion mismatch!');
} }
} }

View File

@@ -44,7 +44,7 @@ contract TestOrder is MockEnv, Test {
uint256 amount = 100000000000000000000; uint256 amount = 100000000000000000000;
SwapOrder memory order = SwapOrder( SwapOrder memory order = SwapOrder(
0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9, 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1, 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9, 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1,
Route(Exchange.UniswapV3, 500), amount, amount/100, true, false, Route(Exchange.UniswapV3, 500), amount, amount/100, true, false, false,
NO_CONDITIONAL_ORDER, tranches NO_CONDITIONAL_ORDER, tranches
); );
console2.logBytes(abi.encode(order)); console2.logBytes(abi.encode(order));
@@ -81,7 +81,7 @@ contract TestExecute is TestOrder {
SwapOrder memory order = SwapOrder( SwapOrder memory order = SwapOrder(
address(COIN), address(USD), // sell COIN for USD address(COIN), address(USD), // sell COIN for USD
Route(Exchange.UniswapV3, 500), amount, amount/100, false, false, Route(Exchange.UniswapV3, 500), amount, amount/100, false, false,
NO_CONDITIONAL_ORDER, tranches false, NO_CONDITIONAL_ORDER, tranches
); );
exactOutputOrderIndex = vault.numSwapOrders(); exactOutputOrderIndex = vault.numSwapOrders();
vault.placeDexorder(order); vault.placeDexorder(order);
@@ -95,7 +95,7 @@ contract TestExecute is TestOrder {
order = SwapOrder( order = SwapOrder(
address(COIN), address(USD), // sell COIN for USD address(COIN), address(USD), // sell COIN for USD
Route(Exchange.UniswapV3, fee), amount, amount/100, true, false, Route(Exchange.UniswapV3, fee), amount, amount/100, true, false,
NO_CONDITIONAL_ORDER, tranches false, NO_CONDITIONAL_ORDER, tranches
); );
exactInputOrderIndex = vault.numSwapOrders(); exactInputOrderIndex = vault.numSwapOrders();
vault.placeDexorder(order); vault.placeDexorder(order);
@@ -126,7 +126,7 @@ contract TestExecute is TestOrder {
SwapOrder memory order = SwapOrder( SwapOrder memory order = SwapOrder(
token0, token1, // sell token0, token1, // sell
Route(Exchange.UniswapV3, fee), amount, amount/100, true, false, Route(Exchange.UniswapV3, fee), amount, amount/100, true, false,
NO_CONDITIONAL_ORDER, tranches false, NO_CONDITIONAL_ORDER, tranches
); );
limitOrderIndex = vault.numSwapOrders(); limitOrderIndex = vault.numSwapOrders();
vault.placeDexorder(order); vault.placeDexorder(order);