TimedOrder submission works

This commit is contained in:
Tim Olson
2023-12-04 17:59:57 -04:00
parent 9797632ac6
commit c9ccb89d8e
8 changed files with 138 additions and 114 deletions

View File

@@ -47,17 +47,48 @@ export const mockErc20Abi = [...erc20Abi,
'function mint(address,uint256)',
]
const Route = '(uint8,uint24)'
const Constraint = '(uint8,bytes)'
const Tranche = `(uint64,${Constraint}[])`
const SwapOrder = `(address,address,${Route},uint256,bool,bool,uint64,${Tranche}[])`
const Route = '(uint8 exchange, uint24 fee)'
const Tranche = `(
uint16 fraction,
bool startTimeIsRelative,
bool endTimeIsRelative,
bool minIsBarrier,
bool maxIsBarrier,
bool marketOrder,
bool _reserved5,
bool _reserved6,
bool _reserved7,
uint8 _reserved8,
uint32 _reserved16,
uint32 startTime,
uint32 endTime,
uint32 minIntercept,
uint32 minSlope,
uint32 maxIntercept,
uint32 maxSlope
)`
const SwapOrder = `(
address tokenIn,
address tokenOut,
${Route} route,
uint256 amount,
uint256 minFillAmount,
bool amountIsInput,
bool outputDirectlyToOwner,
uint64 chainOrder,
${Tranche}[] tranches
)`
export const vaultAbi = [
'function withdraw(uint256)',
'function withdrawTo(address payable,uint256)',
'function withdraw(address,uint256)',
'function withdrawTo(address,address,uint256)',
'function placeOrder((address,address,(uint8,uint24),uint256,bool,bool,uint64,(uint16,(uint8,bytes)[])[]))',
'function placeOrders((address,address,(uint8,uint24),uint256,bool,bool,uint64,(uint16,(uint8,bytes)[])[])[],uint8)',
'function cancelOrder(uint64)',
'function withdraw(uint256 amount)',
'function withdrawTo(address payable recipient, uint256 amount)',
'function withdraw(address token, uint256 amount)',
'function withdrawTo(address token, address recipient, uint256 amount)',
'function numSwapOrders() view returns (uint64 num)',
`function placeOrder(${SwapOrder})`,
`function placeOrders(${SwapOrder}[], uint8 ocoMode)`,
'function cancelOrder(uint64 orderIndex)',
'function cancelAll()',
// `function swapOrderStatus(uint64 orderIndex) view returns (${SwapOrderStatus} memory status)`,
'function orderCanceled(uint64 orderIndex) view returns (bool)',
]

View File

@@ -12,9 +12,10 @@ export function applyFills( orderStatus, filled ) {
export function encodeIEE754(value) {
const buffer = new ArrayBuffer(2);
new DataView(buffer).setFloat32(0, value, false /* big endian */);
return buffer;
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setFloat32(0, value, false /* big endian */);
return view.getUint32(0, false);
}

View File

@@ -1,14 +1,18 @@
import {uint32max, uint64max} from "@/misc.js";
import {ethers} from "ethers";
import {encodeIEE754} from "@/blockchain/common.js";
export const MAX_FRACTION = 65535;
export const NO_CHAIN = uint64max;
export const NO_OCO = uint64max;
export const DISTANT_PAST = 0
export const DISTANT_FUTURE = uint32max
// struct SwapOrder {
// address tokenIn;
// address tokenOut;
// Route route;
// uint256 amount;
// uint256 minFillAmount; // if a tranche has less than this amount available to fill, it is considered completed
// bool amountIsInput;
// bool outputDirectlyToOwner;
// uint64 chainOrder; // use NO_CHAIN for no chaining. chainOrder index must be < than this order's index for safety (written first) and chainOrder state must be Template
@@ -18,24 +22,68 @@ export const NO_OCO = uint64max;
// Exchange exchange;
// uint24 fee;
// }
export function newOrder(tokenIn, tokenOut, exchange, fee, amount, amountIsInput, tranches,
outputToOwner=false, chainOrder=NO_CHAIN) {
if(!tranches)
tranches = [newTranche(1,[])] // todo this is just a swap: issue warning?
return [
tokenIn, tokenOut, [exchange,fee], amount, amountIsInput, outputToOwner, chainOrder, tranches
]
export function newOrder(tokenIn, tokenOut, exchange, fee, amount, amountIsInput, tranches, minAmount=null,
outputToOwner = false, chainOrder = NO_CHAIN) {
if (!tranches)
tranches = [newTranche({marketOrder: true})] // todo this is just a swap: issue warning?
if( minAmount === null )
minAmount = BigInt(amount) / 100n // default to min trade size of 1%
return [tokenIn, tokenOut, [exchange, fee], amount, minAmount, amountIsInput, outputToOwner, chainOrder, tranches]
}
// struct Tranche {
// uint64 fraction;
// Constraint[] constraints;
// uint16 fraction;
//
// bool startTimeIsRelative;
// bool endTimeIsRelative;
// bool minIsBarrier;
// bool maxIsBarrier;
// bool marketOrder; // if true, both min and max lines are ignored, and minIntercept is treated as a maximum slippage value (use positive numbers)
// bool _reserved5;
// bool _reserved6;
// bool _reserved7;
// uint8 _reserved8;
// uint32 _reserved16;
//
// uint32 startTime; // use DISTANT_PAST to disable
// uint32 endTime; // use DISTANT_FUTURE to disable
//
// // if intercept and slope are both 0 the line is disabled
// float minIntercept; // if marketOrder==true, this is the (positive) max slippage amount
// float minSlope;
// float maxIntercept;
// float maxSlope;
// }
export function newTranche(amountRatio, constraints) {
return [
BigInt(Math.min(65535, Math.ceil(amountRatio * 65535))), // we use ceil to make sure the sum of tranche fractions doesn't round below 1
constraints
]
export function newTranche({
fraction = MAX_FRACTION,
marketOrder = false,
startTimeIsRelative = false,
startTime = DISTANT_PAST,
endTimeIsRelative = false,
endTime = DISTANT_FUTURE,
minIsBarrier = false,
minIntercept = 0,
minSlope = 0,
maxIsBarrier = false,
maxIntercept = 0,
maxSlope = 0,
} = {}) {
if( minIntercept === 0 && minSlope === 0 && maxIntercept === 0 && maxSlope === 0 )
marketOrder = true
if( marketOrder )
minIntercept = encodeIEE754(minIntercept) // this is the slippage field for market orders
else {
minIntercept = encodeIEE754(minIntercept)
minSlope = encodeIEE754(minSlope)
maxIntercept = encodeIEE754(maxIntercept)
maxSlope = encodeIEE754(maxSlope)
}
return {
fraction: Math.min(MAX_FRACTION, Math.round(fraction)), marketOrder,
startTimeIsRelative, startTime, endTimeIsRelative, endTime,
minIsBarrier, minIntercept, minSlope, maxIsBarrier, maxIntercept, maxSlope,
_reserved5: false, _reserved6: false, _reserved7: false, _reserved8: 0, _reserved16: 0,
}
}
// enum Exchange {
@@ -47,72 +95,6 @@ export const Exchange = {
UniswapV3: 1,
}
// enum ConstraintMode {
// Time, // 0
// Line, // 1
// Barrier // 2
// }
export const ConstraintMode = {
Time: 0,
Line: 1,
Barrier: 2,
}
// struct Constraint {
// ConstraintMode mode;
// bytes constraint; // abi-encoded constraint struct
// }
function encodeConstraint( constraintMode, types, values ) {
return [constraintMode, ethers.AbiCoder.defaultAbiCoder().encode(types,values)]
}
export const TimeMode = {
Timestamp:0,
SinceOrderStart:1,
}
export const DISTANT_PAST = 0
export const DISTANT_FUTURE = uint32max
// struct Time {
// TimeMode mode;
// uint32 time;
// }
// struct TimeConstraint {
// Time earliest;
// Time latest;
// }
export function newTimeConstraint(startMode, start, endMode, end) {
// absolute time
return encodeConstraint(
ConstraintMode.Time,
['uint8', 'uint32', 'uint8', 'uint32'],
[startMode, start, endMode, end]
)
}
// struct LineConstraint {
// bool isAbove;
// bool isRatio;
// uint32 time;
// uint160 valueSqrtX96;
// int160 slopeSqrtX96; // price change per second
// }
export function newLimitConstraint( isAbove, isRatio, price ) {
return newLineConstraint(isAbove, isRatio, 0, price, 0)
}
export function newLineConstraint( isAbove, isRatio, time, price, slope ) {
return encodeConstraint(
ConstraintMode.Line,
['bool', 'bool', 'uint32', 'uint160', 'int160'],
[isAbove, isRatio, time, sqrtX96(price), sqrtX96(slope)]
)
}
export function sqrtX96(value) {
return BigInt(Math.round(Math.sqrt(value * 2 ** (96*2))))
}