prereq code for otc orders in asset-swapper (#565)
* prereq code for otc orders in asset-swapper * update changelog * add pr to changelog Co-authored-by: Noah Khamliche <0xnoah@Noahs-MacBook-Pro-2.local>
This commit is contained in:
parent
1fb44a55b4
commit
036a263267
@ -1,4 +1,12 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "0.37.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add support for OTC orders in the FillQuoteTransformer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1661462289,
|
"timestamp": 1661462289,
|
||||||
"version": "0.36.6",
|
"version": "0.36.6",
|
||||||
|
@ -31,6 +31,7 @@ import "../features/libs/LibNativeOrder.sol";
|
|||||||
import "./bridges/IBridgeAdapter.sol";
|
import "./bridges/IBridgeAdapter.sol";
|
||||||
import "./Transformer.sol";
|
import "./Transformer.sol";
|
||||||
import "./LibERC20Transformer.sol";
|
import "./LibERC20Transformer.sol";
|
||||||
|
import "../IZeroEx.sol";
|
||||||
|
|
||||||
/// @dev A transformer that fills an ERC20 market sell/buy quote.
|
/// @dev A transformer that fills an ERC20 market sell/buy quote.
|
||||||
/// This transformer shortcuts bridge orders and fills them directly
|
/// This transformer shortcuts bridge orders and fills them directly
|
||||||
@ -52,7 +53,8 @@ contract FillQuoteTransformer is
|
|||||||
enum OrderType {
|
enum OrderType {
|
||||||
Bridge,
|
Bridge,
|
||||||
Limit,
|
Limit,
|
||||||
Rfq
|
Rfq,
|
||||||
|
Otc
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LimitOrderInfo {
|
struct LimitOrderInfo {
|
||||||
@ -69,6 +71,13 @@ contract FillQuoteTransformer is
|
|||||||
uint256 maxTakerTokenFillAmount;
|
uint256 maxTakerTokenFillAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct OtcOrderInfo {
|
||||||
|
LibNativeOrder.OtcOrder order;
|
||||||
|
LibSignature.Signature signature;
|
||||||
|
// Maximum taker token amount of this limit order to fill.
|
||||||
|
uint256 maxTakerTokenFillAmount;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Transform data to ABI-encode and pass into `transform()`.
|
/// @dev Transform data to ABI-encode and pass into `transform()`.
|
||||||
struct TransformData {
|
struct TransformData {
|
||||||
// Whether we are performing a market sell or buy.
|
// Whether we are performing a market sell or buy.
|
||||||
@ -84,6 +93,8 @@ contract FillQuoteTransformer is
|
|||||||
IBridgeAdapter.BridgeOrder[] bridgeOrders;
|
IBridgeAdapter.BridgeOrder[] bridgeOrders;
|
||||||
// Native limit orders. Sorted by fill sequence.
|
// Native limit orders. Sorted by fill sequence.
|
||||||
LimitOrderInfo[] limitOrders;
|
LimitOrderInfo[] limitOrders;
|
||||||
|
// Otc orders. Sorted by fill sequence.
|
||||||
|
OtcOrderInfo[] otcOrders;
|
||||||
// Native RFQ orders. Sorted by fill sequence.
|
// Native RFQ orders. Sorted by fill sequence.
|
||||||
RfqOrderInfo[] rfqOrders;
|
RfqOrderInfo[] rfqOrders;
|
||||||
|
|
||||||
@ -123,7 +134,7 @@ contract FillQuoteTransformer is
|
|||||||
uint256 soldAmount;
|
uint256 soldAmount;
|
||||||
uint256 protocolFee;
|
uint256 protocolFee;
|
||||||
uint256 takerTokenBalanceRemaining;
|
uint256 takerTokenBalanceRemaining;
|
||||||
uint256[3] currentIndices;
|
uint256[4] currentIndices;
|
||||||
OrderType currentOrderType;
|
OrderType currentOrderType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,12 +158,12 @@ contract FillQuoteTransformer is
|
|||||||
IBridgeAdapter public immutable bridgeAdapter;
|
IBridgeAdapter public immutable bridgeAdapter;
|
||||||
|
|
||||||
/// @dev The exchange proxy contract.
|
/// @dev The exchange proxy contract.
|
||||||
INativeOrdersFeature public immutable zeroEx;
|
IZeroEx public immutable zeroEx;
|
||||||
|
|
||||||
/// @dev Create this contract.
|
/// @dev Create this contract.
|
||||||
/// @param bridgeAdapter_ The bridge adapter contract.
|
/// @param bridgeAdapter_ The bridge adapter contract.
|
||||||
/// @param zeroEx_ The Exchange Proxy contract.
|
/// @param zeroEx_ The Exchange Proxy contract.
|
||||||
constructor(IBridgeAdapter bridgeAdapter_, INativeOrdersFeature zeroEx_)
|
constructor(IBridgeAdapter bridgeAdapter_, IZeroEx zeroEx_)
|
||||||
public
|
public
|
||||||
Transformer()
|
Transformer()
|
||||||
{
|
{
|
||||||
@ -183,7 +194,8 @@ contract FillQuoteTransformer is
|
|||||||
|
|
||||||
if (data.bridgeOrders.length
|
if (data.bridgeOrders.length
|
||||||
+ data.limitOrders.length
|
+ data.limitOrders.length
|
||||||
+ data.rfqOrders.length != data.fillSequence.length
|
+ data.rfqOrders.length
|
||||||
|
+ data.otcOrders.length != data.fillSequence.length
|
||||||
) {
|
) {
|
||||||
LibTransformERC20RichErrors.InvalidTransformDataError(
|
LibTransformERC20RichErrors.InvalidTransformDataError(
|
||||||
LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_ARRAY_LENGTH,
|
LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_ARRAY_LENGTH,
|
||||||
@ -198,7 +210,7 @@ contract FillQuoteTransformer is
|
|||||||
|
|
||||||
// Approve the exchange proxy to spend our sell tokens if native orders
|
// Approve the exchange proxy to spend our sell tokens if native orders
|
||||||
// are present.
|
// are present.
|
||||||
if (data.limitOrders.length + data.rfqOrders.length != 0) {
|
if (data.limitOrders.length + data.rfqOrders.length + data.otcOrders.length != 0) {
|
||||||
data.sellToken.approveIfBelow(address(zeroEx), data.fillAmount);
|
data.sellToken.approveIfBelow(address(zeroEx), data.fillAmount);
|
||||||
// Compute the protocol fee if a limit order is present.
|
// Compute the protocol fee if a limit order is present.
|
||||||
if (data.limitOrders.length != 0) {
|
if (data.limitOrders.length != 0) {
|
||||||
@ -230,6 +242,8 @@ contract FillQuoteTransformer is
|
|||||||
results = _fillLimitOrder(data.limitOrders[orderIndex], data, state);
|
results = _fillLimitOrder(data.limitOrders[orderIndex], data, state);
|
||||||
} else if (state.currentOrderType == OrderType.Rfq) {
|
} else if (state.currentOrderType == OrderType.Rfq) {
|
||||||
results = _fillRfqOrder(data.rfqOrders[orderIndex], data, state);
|
results = _fillRfqOrder(data.rfqOrders[orderIndex], data, state);
|
||||||
|
} else if (state.currentOrderType == OrderType.Otc) {
|
||||||
|
results = _fillOtcOrder(data.otcOrders[orderIndex], data, state);
|
||||||
} else {
|
} else {
|
||||||
revert("INVALID_ORDER_TYPE");
|
revert("INVALID_ORDER_TYPE");
|
||||||
}
|
}
|
||||||
@ -402,6 +416,42 @@ contract FillQuoteTransformer is
|
|||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill a single OTC order.
|
||||||
|
function _fillOtcOrder(
|
||||||
|
OtcOrderInfo memory orderInfo,
|
||||||
|
TransformData memory data,
|
||||||
|
FillState memory state
|
||||||
|
)
|
||||||
|
private
|
||||||
|
returns (FillOrderResults memory results)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint256 takerTokenFillAmount = LibSafeMathV06.min256(
|
||||||
|
_computeTakerTokenFillAmount(
|
||||||
|
data,
|
||||||
|
state,
|
||||||
|
orderInfo.order.takerAmount,
|
||||||
|
orderInfo.order.makerAmount,
|
||||||
|
0
|
||||||
|
),
|
||||||
|
orderInfo.maxTakerTokenFillAmount
|
||||||
|
);
|
||||||
|
try
|
||||||
|
zeroEx.fillOtcOrder
|
||||||
|
(
|
||||||
|
orderInfo.order,
|
||||||
|
orderInfo.signature,
|
||||||
|
takerTokenFillAmount.safeDowncastToUint128()
|
||||||
|
)
|
||||||
|
returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
|
||||||
|
{
|
||||||
|
results.takerTokenSoldAmount = takerTokenFilledAmount;
|
||||||
|
results.makerTokenBoughtAmount = makerTokenFilledAmount;
|
||||||
|
} catch {
|
||||||
|
revert("FillQuoteTransformer/OTC_ORDER_FILL_FAILED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Compute the next taker token fill amount of a generic order.
|
// Compute the next taker token fill amount of a generic order.
|
||||||
function _computeTakerTokenFillAmount(
|
function _computeTakerTokenFillAmount(
|
||||||
TransformData memory data,
|
TransformData memory data,
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "11.16.7",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add otc order info to transformer_utils",
|
||||||
|
"pr": "565"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1661462289,
|
"timestamp": 1661462289,
|
||||||
"version": "11.16.6",
|
"version": "11.16.6",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { AbiEncoder, BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
|
import { AbiEncoder, BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
|
||||||
import * as ethjs from 'ethereumjs-util';
|
import * as ethjs from 'ethereumjs-util';
|
||||||
|
|
||||||
import { LimitOrder, LimitOrderFields, RfqOrder, RfqOrderFields } from './orders';
|
import { LimitOrder, LimitOrderFields, RfqOrder, RfqOrderFields, OtcOrder, OtcOrderFields } from './orders';
|
||||||
import { Signature, SIGNATURE_ABI } from './signature_utils';
|
import { Signature, SIGNATURE_ABI } from './signature_utils';
|
||||||
|
|
||||||
const BRIDGE_ORDER_ABI_COMPONENTS = [
|
const BRIDGE_ORDER_ABI_COMPONENTS = [
|
||||||
@ -39,6 +39,20 @@ const RFQ_ORDER_INFO_ABI_COMPONENTS = [
|
|||||||
{ name: 'maxTakerTokenFillAmount', type: 'uint256' },
|
{ name: 'maxTakerTokenFillAmount', type: 'uint256' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const OTC_ORDER_INFO_ABI_COMPONENTS = [
|
||||||
|
{
|
||||||
|
name: 'order',
|
||||||
|
type: 'tuple',
|
||||||
|
components: OtcOrder.STRUCT_ABI,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'signature',
|
||||||
|
type: 'tuple',
|
||||||
|
components: SIGNATURE_ABI,
|
||||||
|
},
|
||||||
|
{ name: 'maxTakerTokenFillAmount', type: 'uint256' },
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ABI encoder for `FillQuoteTransformer.TransformData`
|
* ABI encoder for `FillQuoteTransformer.TransformData`
|
||||||
*/
|
*/
|
||||||
@ -60,6 +74,11 @@ export const fillQuoteTransformerDataEncoder = AbiEncoder.create([
|
|||||||
type: 'tuple[]',
|
type: 'tuple[]',
|
||||||
components: LIMIT_ORDER_INFO_ABI_COMPONENTS,
|
components: LIMIT_ORDER_INFO_ABI_COMPONENTS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'otcOrders',
|
||||||
|
type: 'tuple[]',
|
||||||
|
components: OTC_ORDER_INFO_ABI_COMPONENTS,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'rfqOrders',
|
name: 'rfqOrders',
|
||||||
type: 'tuple[]',
|
type: 'tuple[]',
|
||||||
@ -87,6 +106,7 @@ export enum FillQuoteTransformerOrderType {
|
|||||||
Bridge,
|
Bridge,
|
||||||
Limit,
|
Limit,
|
||||||
Rfq,
|
Rfq,
|
||||||
|
Otc
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,6 +119,7 @@ export interface FillQuoteTransformerData {
|
|||||||
bridgeOrders: FillQuoteTransformerBridgeOrder[];
|
bridgeOrders: FillQuoteTransformerBridgeOrder[];
|
||||||
limitOrders: FillQuoteTransformerLimitOrderInfo[];
|
limitOrders: FillQuoteTransformerLimitOrderInfo[];
|
||||||
rfqOrders: FillQuoteTransformerRfqOrderInfo[];
|
rfqOrders: FillQuoteTransformerRfqOrderInfo[];
|
||||||
|
otcOrders: FillQuoteTransformerOtcOrderInfo[];
|
||||||
fillSequence: FillQuoteTransformerOrderType[];
|
fillSequence: FillQuoteTransformerOrderType[];
|
||||||
fillAmount: BigNumber;
|
fillAmount: BigNumber;
|
||||||
refundReceiver: string;
|
refundReceiver: string;
|
||||||
@ -178,6 +199,11 @@ export type FillQuoteTransformerLimitOrderInfo = FillQuoteTransformerNativeOrder
|
|||||||
*/
|
*/
|
||||||
export type FillQuoteTransformerRfqOrderInfo = FillQuoteTransformerNativeOrderInfo<RfqOrderFields>;
|
export type FillQuoteTransformerRfqOrderInfo = FillQuoteTransformerNativeOrderInfo<RfqOrderFields>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `FillQuoteTransformer.OtcOrderInfo`
|
||||||
|
*/
|
||||||
|
export type FillQuoteTransformerOtcOrderInfo = FillQuoteTransformerNativeOrderInfo<OtcOrderFields>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ABI-encode a `FillQuoteTransformer.TransformData` type.
|
* ABI-encode a `FillQuoteTransformer.TransformData` type.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user