Compare commits
	
		
			5 Commits
		
	
	
		
			@0x/contra
			...
			phil/mkr-4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2baaa2b2db | ||
| 
						 | 
					71292a14ae | ||
| 
						 | 
					46b3d5b1ab | ||
| 
						 | 
					b4cf5d5711 | ||
| 
						 | 
					f69b19faca | 
@@ -20,22 +20,17 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
import "../libs/LibNativeOrder.sol";
 | 
			
		||||
import "./INativeOrdersEvents.sol";
 | 
			
		||||
 | 
			
		||||
import '@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol';
 | 
			
		||||
import '../libs/LibSignature.sol';
 | 
			
		||||
import '../libs/LibNativeOrder.sol';
 | 
			
		||||
import './INativeOrdersEvents.sol';
 | 
			
		||||
 | 
			
		||||
/// @dev Feature for interacting with limit orders.
 | 
			
		||||
interface INativeOrdersFeature is
 | 
			
		||||
    INativeOrdersEvents
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
interface INativeOrdersFeature is INativeOrdersEvents {
 | 
			
		||||
    /// @dev Transfers protocol fees from the `FeeCollector` pools into
 | 
			
		||||
    ///      the staking contract.
 | 
			
		||||
    /// @param poolIds Staking pool IDs
 | 
			
		||||
    function transferProtocolFeesForPools(bytes32[] calldata poolIds)
 | 
			
		||||
        external;
 | 
			
		||||
    function transferProtocolFeesForPools(bytes32[] calldata poolIds) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill a limit order. The taker and sender will be the caller.
 | 
			
		||||
    /// @param order The limit order. ETH protocol fees can be
 | 
			
		||||
@@ -49,10 +44,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        LibNativeOrder.LimitOrder calldata order,
 | 
			
		||||
        LibSignature.Signature calldata signature,
 | 
			
		||||
        uint128 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
 | 
			
		||||
    ) external payable returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order for up to `takerTokenFillAmount` taker tokens.
 | 
			
		||||
    ///      The taker will be the caller.
 | 
			
		||||
@@ -65,9 +57,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        LibNativeOrder.RfqOrder calldata order,
 | 
			
		||||
        LibSignature.Signature calldata signature,
 | 
			
		||||
        uint128 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
 | 
			
		||||
    ) external returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order for exactly `takerTokenFillAmount` taker tokens.
 | 
			
		||||
    ///      The taker will be the caller. ETH protocol fees can be
 | 
			
		||||
@@ -81,10 +71,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        LibNativeOrder.LimitOrder calldata order,
 | 
			
		||||
        LibSignature.Signature calldata signature,
 | 
			
		||||
        uint128 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint128 makerTokenFilledAmount);
 | 
			
		||||
    ) external payable returns (uint128 makerTokenFilledAmount);
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order for exactly `takerTokenFillAmount` taker tokens.
 | 
			
		||||
    ///      The taker will be the caller.
 | 
			
		||||
@@ -96,9 +83,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        LibNativeOrder.RfqOrder calldata order,
 | 
			
		||||
        LibSignature.Signature calldata signature,
 | 
			
		||||
        uint128 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint128 makerTokenFilledAmount);
 | 
			
		||||
    ) external returns (uint128 makerTokenFilledAmount);
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill a limit order. Internal variant. ETH protocol fees can be
 | 
			
		||||
    ///      attached to this call. Any unspent ETH will be refunded to
 | 
			
		||||
@@ -116,10 +101,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        uint128 takerTokenFillAmount,
 | 
			
		||||
        address taker,
 | 
			
		||||
        address sender
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
 | 
			
		||||
    ) external payable returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order. Internal variant.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
@@ -138,40 +120,33 @@ interface INativeOrdersFeature is
 | 
			
		||||
        address taker,
 | 
			
		||||
        bool useSelfBalance,
 | 
			
		||||
        address recipient
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
 | 
			
		||||
    ) external returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount);
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel a single limit order. The caller must be the maker or a valid order signer.
 | 
			
		||||
    ///      Silently succeeds if the order has already been cancelled.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
    function cancelLimitOrder(LibNativeOrder.LimitOrder calldata order)
 | 
			
		||||
        external;
 | 
			
		||||
    function cancelLimitOrder(LibNativeOrder.LimitOrder calldata order) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel a single RFQ order. The caller must be the maker or a valid order signer.
 | 
			
		||||
    ///      Silently succeeds if the order has already been cancelled.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    function cancelRfqOrder(LibNativeOrder.RfqOrder calldata order)
 | 
			
		||||
        external;
 | 
			
		||||
    function cancelRfqOrder(LibNativeOrder.RfqOrder calldata order) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Mark what tx.origin addresses are allowed to fill an order that
 | 
			
		||||
    ///      specifies the message sender as its txOrigin.
 | 
			
		||||
    /// @param origins An array of origin addresses to update.
 | 
			
		||||
    /// @param allowed True to register, false to unregister.
 | 
			
		||||
    function registerAllowedRfqOrigins(address[] memory origins, bool allowed)
 | 
			
		||||
        external;
 | 
			
		||||
    function registerAllowedRfqOrigins(address[] memory origins, bool allowed) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel multiple limit orders. The caller must be the maker or a valid order signer.
 | 
			
		||||
    ///      Silently succeeds if the order has already been cancelled.
 | 
			
		||||
    /// @param orders The limit orders.
 | 
			
		||||
    function batchCancelLimitOrders(LibNativeOrder.LimitOrder[] calldata orders)
 | 
			
		||||
        external;
 | 
			
		||||
    function batchCancelLimitOrders(LibNativeOrder.LimitOrder[] calldata orders) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel multiple RFQ orders. The caller must be the maker or a valid order signer.
 | 
			
		||||
    ///      Silently succeeds if the order has already been cancelled.
 | 
			
		||||
    /// @param orders The RFQ orders.
 | 
			
		||||
    function batchCancelRfqOrders(LibNativeOrder.RfqOrder[] calldata orders)
 | 
			
		||||
        external;
 | 
			
		||||
    function batchCancelRfqOrders(LibNativeOrder.RfqOrder[] calldata orders) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all limit orders for a given maker and pair with a salt less
 | 
			
		||||
    ///      than the value provided. The caller must be the maker. Subsequent
 | 
			
		||||
@@ -184,8 +159,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        IERC20TokenV06 makerToken,
 | 
			
		||||
        IERC20TokenV06 takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all limit orders for a given maker and pair with a salt less
 | 
			
		||||
    ///      than the value provided. The caller must be a signer registered to the maker.
 | 
			
		||||
@@ -200,8 +174,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        IERC20TokenV06 makerToken,
 | 
			
		||||
        IERC20TokenV06 takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all limit orders for a given maker and pairs with salts less
 | 
			
		||||
    ///      than the values provided. The caller must be the maker. Subsequent
 | 
			
		||||
@@ -214,8 +187,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        IERC20TokenV06[] calldata makerTokens,
 | 
			
		||||
        IERC20TokenV06[] calldata takerTokens,
 | 
			
		||||
        uint256[] calldata minValidSalts
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all limit orders for a given maker and pairs with salts less
 | 
			
		||||
    ///      than the values provided. The caller must be a signer registered to the maker.
 | 
			
		||||
@@ -230,8 +202,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        IERC20TokenV06[] memory makerTokens,
 | 
			
		||||
        IERC20TokenV06[] memory takerTokens,
 | 
			
		||||
        uint256[] memory minValidSalts
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all RFQ orders for a given maker and pair with a salt less
 | 
			
		||||
    ///      than the value provided. The caller must be the maker. Subsequent
 | 
			
		||||
@@ -244,8 +215,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        IERC20TokenV06 makerToken,
 | 
			
		||||
        IERC20TokenV06 takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all RFQ orders for a given maker and pair with a salt less
 | 
			
		||||
    ///      than the value provided. The caller must be a signer registered to the maker.
 | 
			
		||||
@@ -260,8 +230,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        IERC20TokenV06 makerToken,
 | 
			
		||||
        IERC20TokenV06 takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all RFQ orders for a given maker and pairs with salts less
 | 
			
		||||
    ///      than the values provided. The caller must be the maker. Subsequent
 | 
			
		||||
@@ -274,8 +243,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        IERC20TokenV06[] calldata makerTokens,
 | 
			
		||||
        IERC20TokenV06[] calldata takerTokens,
 | 
			
		||||
        uint256[] calldata minValidSalts
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all RFQ orders for a given maker and pairs with salts less
 | 
			
		||||
    ///      than the values provided. The caller must be a signer registered to the maker.
 | 
			
		||||
@@ -290,8 +258,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
        IERC20TokenV06[] memory makerTokens,
 | 
			
		||||
        IERC20TokenV06[] memory takerTokens,
 | 
			
		||||
        uint256[] memory minValidSalts
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the order info for a limit order.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
@@ -312,26 +279,17 @@ interface INativeOrdersFeature is
 | 
			
		||||
    /// @dev Get the canonical hash of a limit order.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
    /// @return orderHash The order hash.
 | 
			
		||||
    function getLimitOrderHash(LibNativeOrder.LimitOrder calldata order)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes32 orderHash);
 | 
			
		||||
    function getLimitOrderHash(LibNativeOrder.LimitOrder calldata order) external view returns (bytes32 orderHash);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the canonical hash of an RFQ order.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    /// @return orderHash The order hash.
 | 
			
		||||
    function getRfqOrderHash(LibNativeOrder.RfqOrder calldata order)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes32 orderHash);
 | 
			
		||||
    function getRfqOrderHash(LibNativeOrder.RfqOrder calldata order) external view returns (bytes32 orderHash);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the protocol fee multiplier. This should be multiplied by the
 | 
			
		||||
    ///      gas price to arrive at the required protocol fee to fill a native order.
 | 
			
		||||
    /// @return multiplier The protocol fee multiplier.
 | 
			
		||||
    function getProtocolFeeMultiplier()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint32 multiplier);
 | 
			
		||||
    function getProtocolFeeMultiplier() external view returns (uint32 multiplier);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get order info, fillable amount, and signature validity for a limit order.
 | 
			
		||||
    ///      Fillable amount is determined using balances and allowances of the maker.
 | 
			
		||||
@@ -361,10 +319,7 @@ interface INativeOrdersFeature is
 | 
			
		||||
    /// @return actualFillableTakerTokenAmount How much of the order is fillable
 | 
			
		||||
    ///         based on maker funds, in taker tokens.
 | 
			
		||||
    /// @return isSignatureValid Whether the signature is valid.
 | 
			
		||||
    function getRfqOrderRelevantState(
 | 
			
		||||
        LibNativeOrder.RfqOrder calldata order,
 | 
			
		||||
        LibSignature.Signature calldata signature
 | 
			
		||||
    )
 | 
			
		||||
    function getRfqOrderRelevantState(LibNativeOrder.RfqOrder calldata order, LibSignature.Signature calldata signature)
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (
 | 
			
		||||
@@ -419,20 +374,10 @@ interface INativeOrdersFeature is
 | 
			
		||||
    ///      This allows one to sign on behalf of a contract that calls this function
 | 
			
		||||
    /// @param signer The address from which you plan to generate signatures
 | 
			
		||||
    /// @param allowed True to register, false to unregister.
 | 
			
		||||
    function registerAllowedOrderSigner(
 | 
			
		||||
        address signer,
 | 
			
		||||
        bool allowed
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
    function registerAllowedOrderSigner(address signer, bool allowed) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev checks if a given address is registered to sign on behalf of a maker address
 | 
			
		||||
    /// @param maker The maker address encoded in an order (can be a contract)
 | 
			
		||||
    /// @param signer The address that is providing a signature
 | 
			
		||||
    function isValidOrderSigner(
 | 
			
		||||
        address maker,
 | 
			
		||||
        address signer
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (bool isAllowed);
 | 
			
		||||
    function isValidOrderSigner(address maker, address signer) external view returns (bool isAllowed);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,23 +20,22 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
 | 
			
		||||
import "../errors/LibTransformERC20RichErrors.sol";
 | 
			
		||||
import "../features/interfaces/INativeOrdersFeature.sol";
 | 
			
		||||
import "../features/libs/LibNativeOrder.sol";
 | 
			
		||||
import "./bridges/IBridgeAdapter.sol";
 | 
			
		||||
import "./Transformer.sol";
 | 
			
		||||
import "./LibERC20Transformer.sol";
 | 
			
		||||
import '@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol';
 | 
			
		||||
import '@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol';
 | 
			
		||||
import '@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol';
 | 
			
		||||
import '@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol';
 | 
			
		||||
import '@0x/contracts-utils/contracts/src/v06/LibMathV06.sol';
 | 
			
		||||
import '../errors/LibTransformERC20RichErrors.sol';
 | 
			
		||||
import '../features/interfaces/INativeOrdersFeature.sol';
 | 
			
		||||
import '../features/libs/LibNativeOrder.sol';
 | 
			
		||||
import './bridges/IBridgeAdapter.sol';
 | 
			
		||||
import './Transformer.sol';
 | 
			
		||||
import './LibERC20Transformer.sol';
 | 
			
		||||
import '../IZeroEx.sol';
 | 
			
		||||
 | 
			
		||||
/// @dev A transformer that fills an ERC20 market sell/buy quote.
 | 
			
		||||
///      This transformer shortcuts bridge orders and fills them directly
 | 
			
		||||
contract FillQuoteTransformer is
 | 
			
		||||
    Transformer
 | 
			
		||||
{
 | 
			
		||||
contract FillQuoteTransformer is Transformer {
 | 
			
		||||
    using LibERC20TokenV06 for IERC20TokenV06;
 | 
			
		||||
    using LibERC20Transformer for IERC20TokenV06;
 | 
			
		||||
    using LibSafeMathV06 for uint256;
 | 
			
		||||
@@ -52,7 +51,8 @@ contract FillQuoteTransformer is
 | 
			
		||||
    enum OrderType {
 | 
			
		||||
        Bridge,
 | 
			
		||||
        Limit,
 | 
			
		||||
        Rfq
 | 
			
		||||
        Rfq,
 | 
			
		||||
        Otc
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct LimitOrderInfo {
 | 
			
		||||
@@ -69,6 +69,13 @@ contract FillQuoteTransformer is
 | 
			
		||||
        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()`.
 | 
			
		||||
    struct TransformData {
 | 
			
		||||
        // Whether we are performing a market sell or buy.
 | 
			
		||||
@@ -79,26 +86,24 @@ contract FillQuoteTransformer is
 | 
			
		||||
        // The token being bought.
 | 
			
		||||
        // This should be an actual token, not the ETH pseudo-token.
 | 
			
		||||
        IERC20TokenV06 buyToken;
 | 
			
		||||
 | 
			
		||||
        // External liquidity bridge orders. Sorted by fill sequence.
 | 
			
		||||
        IBridgeAdapter.BridgeOrder[] bridgeOrders;
 | 
			
		||||
        // Native limit orders. Sorted by fill sequence.
 | 
			
		||||
        LimitOrderInfo[] limitOrders;
 | 
			
		||||
        // Native RFQ orders. Sorted by fill sequence.
 | 
			
		||||
        RfqOrderInfo[] rfqOrders;
 | 
			
		||||
 | 
			
		||||
        // Otc orders.
 | 
			
		||||
        OtcOrderInfo[] otcOrders;
 | 
			
		||||
        // The sequence to fill the orders in. Each item will fill the next
 | 
			
		||||
        // order of that type in either `bridgeOrders`, `limitOrders`,
 | 
			
		||||
        // or `rfqOrders.`
 | 
			
		||||
        // `rfqOrders`, or `otcOrders.`
 | 
			
		||||
        OrderType[] fillSequence;
 | 
			
		||||
 | 
			
		||||
        // Amount of `sellToken` to sell or `buyToken` to buy.
 | 
			
		||||
        // For sells, setting the high-bit indicates that
 | 
			
		||||
        // `sellAmount & LOW_BITS` should be treated as a `1e18` fraction of
 | 
			
		||||
        // the current balance of `sellToken`, where
 | 
			
		||||
        // `1e18+ == 100%` and `0.5e18 == 50%`, etc.
 | 
			
		||||
        uint256 fillAmount;
 | 
			
		||||
 | 
			
		||||
        // Who to transfer unused protocol fees to.
 | 
			
		||||
        // May be a valid address or one of:
 | 
			
		||||
        // `address(0)`: Stay in flash wallet.
 | 
			
		||||
@@ -123,7 +128,7 @@ contract FillQuoteTransformer is
 | 
			
		||||
        uint256 soldAmount;
 | 
			
		||||
        uint256 protocolFee;
 | 
			
		||||
        uint256 takerTokenBalanceRemaining;
 | 
			
		||||
        uint256[3] currentIndices;
 | 
			
		||||
        uint256[4] currentIndices;
 | 
			
		||||
        OrderType currentOrderType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -133,7 +138,7 @@ contract FillQuoteTransformer is
 | 
			
		||||
    event ProtocolFeeUnfunded(bytes32 orderHash);
 | 
			
		||||
 | 
			
		||||
    /// @dev The highest bit of a uint256 value.
 | 
			
		||||
    uint256 private constant HIGH_BIT = 2 ** 255;
 | 
			
		||||
    uint256 private constant HIGH_BIT = 2**255;
 | 
			
		||||
    /// @dev Mask of the lower 255 bits of a uint256 value.
 | 
			
		||||
    uint256 private constant LOWER_255_BITS = HIGH_BIT - 1;
 | 
			
		||||
    /// @dev If `refundReceiver` is set to this address, unpsent
 | 
			
		||||
@@ -147,15 +152,12 @@ contract FillQuoteTransformer is
 | 
			
		||||
    IBridgeAdapter public immutable bridgeAdapter;
 | 
			
		||||
 | 
			
		||||
    /// @dev The exchange proxy contract.
 | 
			
		||||
    INativeOrdersFeature public immutable zeroEx;
 | 
			
		||||
    IZeroEx public immutable zeroEx;
 | 
			
		||||
 | 
			
		||||
    /// @dev Create this contract.
 | 
			
		||||
    /// @param bridgeAdapter_ The bridge adapter contract.
 | 
			
		||||
    /// @param zeroEx_ The Exchange Proxy contract.
 | 
			
		||||
    constructor(IBridgeAdapter bridgeAdapter_, INativeOrdersFeature zeroEx_)
 | 
			
		||||
        public
 | 
			
		||||
        Transformer()
 | 
			
		||||
    {
 | 
			
		||||
    constructor(IBridgeAdapter bridgeAdapter_, IZeroEx zeroEx_) public Transformer() {
 | 
			
		||||
        bridgeAdapter = bridgeAdapter_;
 | 
			
		||||
        zeroEx = zeroEx_;
 | 
			
		||||
    }
 | 
			
		||||
@@ -165,30 +167,27 @@ contract FillQuoteTransformer is
 | 
			
		||||
    ///      to this call. `buyToken` and excess ETH will be transferred back to the caller.
 | 
			
		||||
    /// @param context Context information.
 | 
			
		||||
    /// @return magicBytes The success bytes (`LibERC20Transformer.TRANSFORMER_SUCCESS`).
 | 
			
		||||
    function transform(TransformContext calldata context)
 | 
			
		||||
        external
 | 
			
		||||
        override
 | 
			
		||||
        returns (bytes4 magicBytes)
 | 
			
		||||
    {
 | 
			
		||||
    function transform(TransformContext calldata context) external override returns (bytes4 magicBytes) {
 | 
			
		||||
        TransformData memory data = abi.decode(context.data, (TransformData));
 | 
			
		||||
        FillState memory state;
 | 
			
		||||
 | 
			
		||||
        // Validate data fields.
 | 
			
		||||
        if (data.sellToken.isTokenETH() || data.buyToken.isTokenETH()) {
 | 
			
		||||
            LibTransformERC20RichErrors.InvalidTransformDataError(
 | 
			
		||||
                LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_TOKENS,
 | 
			
		||||
                context.data
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
            LibTransformERC20RichErrors
 | 
			
		||||
                .InvalidTransformDataError(
 | 
			
		||||
                    LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_TOKENS,
 | 
			
		||||
                    context.data
 | 
			
		||||
                )
 | 
			
		||||
                .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (data.bridgeOrders.length
 | 
			
		||||
                + data.limitOrders.length
 | 
			
		||||
                + data.rfqOrders.length != data.fillSequence.length
 | 
			
		||||
        ) {
 | 
			
		||||
            LibTransformERC20RichErrors.InvalidTransformDataError(
 | 
			
		||||
                LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_ARRAY_LENGTH,
 | 
			
		||||
                context.data
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        if (data.bridgeOrders.length + data.limitOrders.length + data.rfqOrders.length != data.fillSequence.length) {
 | 
			
		||||
            LibTransformERC20RichErrors
 | 
			
		||||
                .InvalidTransformDataError(
 | 
			
		||||
                    LibTransformERC20RichErrors.InvalidTransformDataErrorCode.INVALID_ARRAY_LENGTH,
 | 
			
		||||
                    context.data
 | 
			
		||||
                )
 | 
			
		||||
                .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        state.takerTokenBalanceRemaining = data.sellToken.getTokenBalanceOf(address(this));
 | 
			
		||||
@@ -202,8 +201,7 @@ contract FillQuoteTransformer is
 | 
			
		||||
            data.sellToken.approveIfBelow(address(zeroEx), data.fillAmount);
 | 
			
		||||
            // Compute the protocol fee if a limit order is present.
 | 
			
		||||
            if (data.limitOrders.length != 0) {
 | 
			
		||||
                state.protocolFee = uint256(zeroEx.getProtocolFeeMultiplier())
 | 
			
		||||
                    .safeMul(tx.gasprice);
 | 
			
		||||
                state.protocolFee = uint256(zeroEx.getProtocolFeeMultiplier()).safeMul(tx.gasprice);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -214,10 +212,14 @@ contract FillQuoteTransformer is
 | 
			
		||||
            // Check if we've hit our targets.
 | 
			
		||||
            if (data.side == Side.Sell) {
 | 
			
		||||
                // Market sell check.
 | 
			
		||||
                if (state.soldAmount >= data.fillAmount) { break; }
 | 
			
		||||
                if (state.soldAmount >= data.fillAmount) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                // Market buy check.
 | 
			
		||||
                if (state.boughtAmount >= data.fillAmount) { break; }
 | 
			
		||||
                if (state.boughtAmount >= data.fillAmount) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            state.currentOrderType = OrderType(data.fillSequence[i]);
 | 
			
		||||
@@ -230,19 +232,17 @@ contract FillQuoteTransformer is
 | 
			
		||||
                results = _fillLimitOrder(data.limitOrders[orderIndex], data, state);
 | 
			
		||||
            } else if (state.currentOrderType == OrderType.Rfq) {
 | 
			
		||||
                results = _fillRfqOrder(data.rfqOrders[orderIndex], data, state);
 | 
			
		||||
            } else if (state.currentOrderType == OrderType.Otc) {
 | 
			
		||||
                results = _fillOtcOrder(data.otcOrders[orderIndex], data, state);
 | 
			
		||||
            } else {
 | 
			
		||||
                revert("INVALID_ORDER_TYPE");
 | 
			
		||||
                revert('INVALID_ORDER_TYPE');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Accumulate totals.
 | 
			
		||||
            state.soldAmount = state.soldAmount
 | 
			
		||||
                .safeAdd(results.takerTokenSoldAmount);
 | 
			
		||||
            state.boughtAmount = state.boughtAmount
 | 
			
		||||
                .safeAdd(results.makerTokenBoughtAmount);
 | 
			
		||||
            state.ethRemaining = state.ethRemaining
 | 
			
		||||
                .safeSub(results.protocolFeePaid);
 | 
			
		||||
            state.takerTokenBalanceRemaining = state.takerTokenBalanceRemaining
 | 
			
		||||
                .safeSub(results.takerTokenSoldAmount);
 | 
			
		||||
            state.soldAmount = state.soldAmount.safeAdd(results.takerTokenSoldAmount);
 | 
			
		||||
            state.boughtAmount = state.boughtAmount.safeAdd(results.makerTokenBoughtAmount);
 | 
			
		||||
            state.ethRemaining = state.ethRemaining.safeSub(results.protocolFeePaid);
 | 
			
		||||
            state.takerTokenBalanceRemaining = state.takerTokenBalanceRemaining.safeSub(results.takerTokenSoldAmount);
 | 
			
		||||
            state.currentIndices[uint256(state.currentOrderType)]++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -251,21 +251,15 @@ contract FillQuoteTransformer is
 | 
			
		||||
            // Market sell check.
 | 
			
		||||
            if (state.soldAmount < data.fillAmount) {
 | 
			
		||||
                LibTransformERC20RichErrors
 | 
			
		||||
                    .IncompleteFillSellQuoteError(
 | 
			
		||||
                        address(data.sellToken),
 | 
			
		||||
                        state.soldAmount,
 | 
			
		||||
                        data.fillAmount
 | 
			
		||||
                    ).rrevert();
 | 
			
		||||
                    .IncompleteFillSellQuoteError(address(data.sellToken), state.soldAmount, data.fillAmount)
 | 
			
		||||
                    .rrevert();
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // Market buy check.
 | 
			
		||||
            if (state.boughtAmount < data.fillAmount) {
 | 
			
		||||
                LibTransformERC20RichErrors
 | 
			
		||||
                    .IncompleteFillBuyQuoteError(
 | 
			
		||||
                        address(data.buyToken),
 | 
			
		||||
                        state.boughtAmount,
 | 
			
		||||
                        data.fillAmount
 | 
			
		||||
                    ).rrevert();
 | 
			
		||||
                    .IncompleteFillBuyQuoteError(address(data.buyToken), state.boughtAmount, data.fillAmount)
 | 
			
		||||
                    .rrevert();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -273,13 +267,13 @@ contract FillQuoteTransformer is
 | 
			
		||||
        if (state.ethRemaining > 0 && data.refundReceiver != address(0)) {
 | 
			
		||||
            bool transferSuccess;
 | 
			
		||||
            if (data.refundReceiver == REFUND_RECEIVER_RECIPIENT) {
 | 
			
		||||
                (transferSuccess,) = context.recipient.call{value: state.ethRemaining}("");
 | 
			
		||||
                (transferSuccess, ) = context.recipient.call{ value: state.ethRemaining }('');
 | 
			
		||||
            } else if (data.refundReceiver == REFUND_RECEIVER_SENDER) {
 | 
			
		||||
                (transferSuccess,) = context.sender.call{value: state.ethRemaining}("");
 | 
			
		||||
                (transferSuccess, ) = context.sender.call{ value: state.ethRemaining }('');
 | 
			
		||||
            } else {
 | 
			
		||||
                (transferSuccess,) = data.refundReceiver.call{value: state.ethRemaining}("");
 | 
			
		||||
                (transferSuccess, ) = data.refundReceiver.call{ value: state.ethRemaining }('');
 | 
			
		||||
            }
 | 
			
		||||
            require(transferSuccess, "FillQuoteTransformer/ETHER_TRANSFER_FALIED");
 | 
			
		||||
            require(transferSuccess, 'FillQuoteTransformer/ETHER_TRANSFER_FALIED');
 | 
			
		||||
        }
 | 
			
		||||
        return LibERC20Transformer.TRANSFORMER_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
@@ -289,10 +283,7 @@ contract FillQuoteTransformer is
 | 
			
		||||
        IBridgeAdapter.BridgeOrder memory order,
 | 
			
		||||
        TransformData memory data,
 | 
			
		||||
        FillState memory state
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        returns (FillOrderResults memory results)
 | 
			
		||||
    {
 | 
			
		||||
    ) private returns (FillOrderResults memory results) {
 | 
			
		||||
        uint256 takerTokenFillAmount = _computeTakerTokenFillAmount(
 | 
			
		||||
            data,
 | 
			
		||||
            state,
 | 
			
		||||
@@ -321,10 +312,7 @@ contract FillQuoteTransformer is
 | 
			
		||||
        LimitOrderInfo memory orderInfo,
 | 
			
		||||
        TransformData memory data,
 | 
			
		||||
        FillState memory state
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        returns (FillOrderResults memory results)
 | 
			
		||||
    {
 | 
			
		||||
    ) private returns (FillOrderResults memory results) {
 | 
			
		||||
        uint256 takerTokenFillAmount = LibSafeMathV06.min256(
 | 
			
		||||
            _computeTakerTokenFillAmount(
 | 
			
		||||
                data,
 | 
			
		||||
@@ -344,22 +332,21 @@ contract FillQuoteTransformer is
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
            zeroEx.fillLimitOrder
 | 
			
		||||
                {value: state.protocolFee}
 | 
			
		||||
                (
 | 
			
		||||
                    orderInfo.order,
 | 
			
		||||
                    orderInfo.signature,
 | 
			
		||||
                    takerTokenFillAmount.safeDowncastToUint128()
 | 
			
		||||
                )
 | 
			
		||||
            returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
        {
 | 
			
		||||
            zeroEx.fillLimitOrder{ value: state.protocolFee }(
 | 
			
		||||
                orderInfo.order,
 | 
			
		||||
                orderInfo.signature,
 | 
			
		||||
                takerTokenFillAmount.safeDowncastToUint128()
 | 
			
		||||
            )
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount) {
 | 
			
		||||
            if (orderInfo.order.takerTokenFeeAmount > 0) {
 | 
			
		||||
                takerTokenFilledAmount = takerTokenFilledAmount.safeAdd128(
 | 
			
		||||
                    LibMathV06.getPartialAmountFloor(
 | 
			
		||||
                        takerTokenFilledAmount,
 | 
			
		||||
                        orderInfo.order.takerAmount,
 | 
			
		||||
                        orderInfo.order.takerTokenFeeAmount
 | 
			
		||||
                    ).safeDowncastToUint128()
 | 
			
		||||
                    LibMathV06
 | 
			
		||||
                        .getPartialAmountFloor(
 | 
			
		||||
                            takerTokenFilledAmount,
 | 
			
		||||
                            orderInfo.order.takerAmount,
 | 
			
		||||
                            orderInfo.order.takerTokenFeeAmount
 | 
			
		||||
                        )
 | 
			
		||||
                        .safeDowncastToUint128()
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            results.takerTokenSoldAmount = takerTokenFilledAmount;
 | 
			
		||||
@@ -373,30 +360,34 @@ contract FillQuoteTransformer is
 | 
			
		||||
        RfqOrderInfo memory orderInfo,
 | 
			
		||||
        TransformData memory data,
 | 
			
		||||
        FillState memory state
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        returns (FillOrderResults memory results)
 | 
			
		||||
    {
 | 
			
		||||
    ) private returns (FillOrderResults memory results) {
 | 
			
		||||
        uint256 takerTokenFillAmount = LibSafeMathV06.min256(
 | 
			
		||||
            _computeTakerTokenFillAmount(
 | 
			
		||||
                data,
 | 
			
		||||
                state,
 | 
			
		||||
                orderInfo.order.takerAmount,
 | 
			
		||||
                orderInfo.order.makerAmount,
 | 
			
		||||
                0
 | 
			
		||||
            ),
 | 
			
		||||
            _computeTakerTokenFillAmount(data, state, orderInfo.order.takerAmount, orderInfo.order.makerAmount, 0),
 | 
			
		||||
            orderInfo.maxTakerTokenFillAmount
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
            zeroEx.fillRfqOrder
 | 
			
		||||
                (
 | 
			
		||||
                    orderInfo.order,
 | 
			
		||||
                    orderInfo.signature,
 | 
			
		||||
                    takerTokenFillAmount.safeDowncastToUint128()
 | 
			
		||||
                )
 | 
			
		||||
            returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
        {
 | 
			
		||||
            zeroEx.fillRfqOrder(orderInfo.order, orderInfo.signature, takerTokenFillAmount.safeDowncastToUint128())
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount) {
 | 
			
		||||
            results.takerTokenSoldAmount = takerTokenFilledAmount;
 | 
			
		||||
            results.makerTokenBoughtAmount = makerTokenFilledAmount;
 | 
			
		||||
        } 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 {}
 | 
			
		||||
@@ -409,11 +400,7 @@ contract FillQuoteTransformer is
 | 
			
		||||
        uint256 orderTakerAmount,
 | 
			
		||||
        uint256 orderMakerAmount,
 | 
			
		||||
        uint256 orderTakerTokenFeeAmount
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        pure
 | 
			
		||||
        returns (uint256 takerTokenFillAmount)
 | 
			
		||||
    {
 | 
			
		||||
    ) private pure returns (uint256 takerTokenFillAmount) {
 | 
			
		||||
        if (data.side == Side.Sell) {
 | 
			
		||||
            takerTokenFillAmount = data.fillAmount.safeSub(state.soldAmount);
 | 
			
		||||
            if (orderTakerTokenFeeAmount != 0) {
 | 
			
		||||
@@ -423,34 +410,31 @@ contract FillQuoteTransformer is
 | 
			
		||||
                    orderTakerAmount
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        } else { // Buy
 | 
			
		||||
        } else {
 | 
			
		||||
            // Buy
 | 
			
		||||
            takerTokenFillAmount = LibMathV06.getPartialAmountCeil(
 | 
			
		||||
                data.fillAmount.safeSub(state.boughtAmount),
 | 
			
		||||
                orderMakerAmount,
 | 
			
		||||
                orderTakerAmount
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        return LibSafeMathV06.min256(
 | 
			
		||||
            LibSafeMathV06.min256(takerTokenFillAmount, orderTakerAmount),
 | 
			
		||||
            state.takerTokenBalanceRemaining
 | 
			
		||||
        );
 | 
			
		||||
        return
 | 
			
		||||
            LibSafeMathV06.min256(
 | 
			
		||||
                LibSafeMathV06.min256(takerTokenFillAmount, orderTakerAmount),
 | 
			
		||||
                state.takerTokenBalanceRemaining
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Convert possible proportional values to absolute quantities.
 | 
			
		||||
    function _normalizeFillAmount(uint256 rawAmount, uint256 balance)
 | 
			
		||||
        private
 | 
			
		||||
        pure
 | 
			
		||||
        returns (uint256 normalized)
 | 
			
		||||
    {
 | 
			
		||||
    function _normalizeFillAmount(uint256 rawAmount, uint256 balance) private pure returns (uint256 normalized) {
 | 
			
		||||
        if ((rawAmount & HIGH_BIT) == HIGH_BIT) {
 | 
			
		||||
            // If the high bit of `rawAmount` is set then the lower 255 bits
 | 
			
		||||
            // specify a fraction of `balance`.
 | 
			
		||||
            return LibSafeMathV06.min256(
 | 
			
		||||
                balance
 | 
			
		||||
                    * LibSafeMathV06.min256(rawAmount & LOWER_255_BITS, 1e18)
 | 
			
		||||
                    / 1e18,
 | 
			
		||||
                balance
 | 
			
		||||
            );
 | 
			
		||||
            return
 | 
			
		||||
                LibSafeMathV06.min256(
 | 
			
		||||
                    (balance * LibSafeMathV06.min256(rawAmount & LOWER_255_BITS, 1e18)) / 1e18,
 | 
			
		||||
                    balance
 | 
			
		||||
                );
 | 
			
		||||
        }
 | 
			
		||||
        return rawAmount;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -83,6 +83,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.5.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.8.12",
 | 
			
		||||
        "@0x/protocol-utils": "^11.13.0",
 | 
			
		||||
        "@0x/subproviders": "^6.6.5",
 | 
			
		||||
        "@0x/types": "^3.3.6",
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@ import {
 | 
			
		||||
    FillQuoteTransformerSide as Side,
 | 
			
		||||
    LimitOrder,
 | 
			
		||||
    LimitOrderFields,
 | 
			
		||||
    OtcOrder,
 | 
			
		||||
    OtcOrderFields,
 | 
			
		||||
    RfqOrder,
 | 
			
		||||
    RfqOrderFields,
 | 
			
		||||
    Signature,
 | 
			
		||||
@@ -26,10 +28,11 @@ import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from '../artifacts';
 | 
			
		||||
import { TestFillQuoteTransformerBridgeContract } from '../generated-wrappers/test_fill_quote_transformer_bridge';
 | 
			
		||||
import { getRandomLimitOrder, getRandomRfqOrder } from '../utils/orders';
 | 
			
		||||
import { getRandomLimitOrder, getRandomRfqOrder, getRandomOtcOrder } from '../utils/orders';
 | 
			
		||||
import {
 | 
			
		||||
    BridgeAdapterContract,
 | 
			
		||||
    FillQuoteTransformerContract,
 | 
			
		||||
    OtcOrdersFeatureContract,
 | 
			
		||||
    TestFillQuoteTransformerExchangeContract,
 | 
			
		||||
    TestFillQuoteTransformerHostContract,
 | 
			
		||||
    TestMintableERC20TokenContract,
 | 
			
		||||
@@ -71,6 +74,15 @@ blockchainTests.resets('FillQuoteTransformer', env => {
 | 
			
		||||
            artifacts,
 | 
			
		||||
            NULL_ADDRESS,
 | 
			
		||||
        );
 | 
			
		||||
        const otcOrder = await OtcOrdersFeatureContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.OtcOrdersFeature,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
            NULL_ADDRESS,
 | 
			
		||||
            NULL_ADDRESS, // weth
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        transformer = await FillQuoteTransformerContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.FillQuoteTransformer,
 | 
			
		||||
            env.provider,
 | 
			
		||||
@@ -78,6 +90,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
 | 
			
		||||
            artifacts,
 | 
			
		||||
            bridgeAdapter.address,
 | 
			
		||||
            exchange.address,
 | 
			
		||||
            otcOrder.address
 | 
			
		||||
        );
 | 
			
		||||
        host = await TestFillQuoteTransformerHostContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestFillQuoteTransformerHost,
 | 
			
		||||
@@ -141,6 +154,18 @@ blockchainTests.resets('FillQuoteTransformer', env => {
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createOTCBridgeOrder(fields: Partial<OtcOrderFields> = {}): OtcOrder {
 | 
			
		||||
        return getRandomOtcOrder({
 | 
			
		||||
            makerToken: makerToken.address,
 | 
			
		||||
            takerToken: takerToken.address,
 | 
			
		||||
            makerAmount: getRandomInteger('0.1e18', '1e18'),
 | 
			
		||||
            takerAmount: getRandomInteger('0.1e18', '1e18'),
 | 
			
		||||
            maker,
 | 
			
		||||
            taker,
 | 
			
		||||
            ...fields,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createOrderSignature(preFilledTakerAmount: Numberish = 0): Signature {
 | 
			
		||||
        return {
 | 
			
		||||
            // The r field of the signature is the pre-filled amount.
 | 
			
		||||
@@ -271,6 +296,24 @@ blockchainTests.resets('FillQuoteTransformer', env => {
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function fillOtcOrder(oi: FillQuoteTransformerRfqOrderInfo): FillOrderResults {
 | 
			
		||||
            const preFilledTakerAmount = orderSignatureToPreFilledTakerAmount(oi.signature);
 | 
			
		||||
            if (preFilledTakerAmount.gte(oi.order.takerAmount) || preFilledTakerAmount.eq(REVERT_AMOUNT)) {
 | 
			
		||||
                return EMPTY_FILL_ORDER_RESULTS;
 | 
			
		||||
            }
 | 
			
		||||
            const takerTokenFillAmount = BigNumber.min(
 | 
			
		||||
                computeTakerTokenFillAmount(oi.order.takerAmount, oi.order.makerAmount),
 | 
			
		||||
                oi.order.takerAmount.minus(preFilledTakerAmount),
 | 
			
		||||
                oi.maxTakerTokenFillAmount,
 | 
			
		||||
            );
 | 
			
		||||
            const fillRatio = takerTokenFillAmount.div(oi.order.takerAmount);
 | 
			
		||||
            return {
 | 
			
		||||
                ...EMPTY_FILL_ORDER_RESULTS,
 | 
			
		||||
                takerTokenSoldAmount: takerTokenFillAmount,
 | 
			
		||||
                makerTokenBoughtAmount: fillRatio.times(oi.order.makerAmount).integerValue(BigNumber.ROUND_DOWN),
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // tslint:disable-next-line: prefer-for-of
 | 
			
		||||
        for (let i = 0; i < data.fillSequence.length; ++i) {
 | 
			
		||||
            const orderType = data.fillSequence[i];
 | 
			
		||||
 
 | 
			
		||||
@@ -60,9 +60,10 @@
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/assert": "^3.0.34",
 | 
			
		||||
        "@0x/base-contract": "^6.5.0",
 | 
			
		||||
        "@0x/contract-addresses": "^6.14.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.20.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.30",
 | 
			
		||||
        "@0x/contract-addresses": "^6.16.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.20.4",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.23",
 | 
			
		||||
        "@0x/contracts-zero-ex": "^0.33.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.14",
 | 
			
		||||
        "@0x/json-schemas": "^6.4.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,7 @@ import {
 | 
			
		||||
    FinalUniswapV3FillData,
 | 
			
		||||
    LiquidityProviderFillData,
 | 
			
		||||
    MooniswapFillData,
 | 
			
		||||
    NativeOtcOrderFillData,
 | 
			
		||||
    NativeRfqOrderFillData,
 | 
			
		||||
    OptimizedMarketBridgeOrder,
 | 
			
		||||
    OptimizedMarketOrder,
 | 
			
		||||
@@ -377,7 +378,66 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
 | 
			
		||||
                gasOverhead: ZERO_AMOUNT,
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        if (
 | 
			
		||||
            // select for all chains OtcOrders exists on
 | 
			
		||||
            [ChainId.Mainnet].includes(this.chainId) &&
 | 
			
		||||
            quote.orders.length == 1 &&
 | 
			
		||||
            quote.orders.every(o => o.type === FillQuoteTransformerOrderType.Otc) &&
 | 
			
		||||
            !requiresTransformERC20(optsWithDefaults)
 | 
			
		||||
        ) {
 | 
			
		||||
 | 
			
		||||
            const otcOrdersData = quote.orders.map(o => o.fillData as NativeOtcOrderFillData);
 | 
			
		||||
            const fillAmountPerOrder = (() => {
 | 
			
		||||
                // Don't think order taker amounts are clipped to actual sell amount
 | 
			
		||||
                // (the last one might be too large) so figure them out manually.
 | 
			
		||||
                let remaining = sellAmount;
 | 
			
		||||
                const fillAmounts = [];
 | 
			
		||||
                for (const o of quote.orders) {
 | 
			
		||||
                    const fillAmount = BigNumber.min(o.takerAmount, remaining);
 | 
			
		||||
                    fillAmounts.push(fillAmount);
 | 
			
		||||
                    remaining = remaining.minus(fillAmount);
 | 
			
		||||
                }
 | 
			
		||||
                return fillAmounts;
 | 
			
		||||
            })();
 | 
			
		||||
 | 
			
		||||
            // grab the amount to fill on each OtcOrder (if more than 1)
 | 
			
		||||
            let calldata;
 | 
			
		||||
 | 
			
		||||
            if(isFromETH){
 | 
			
		||||
                calldata = this._exchangeProxy.fillOtcOrderWithEth(
 | 
			
		||||
                    otcOrdersData[0].order, otcOrdersData[0].signature
 | 
			
		||||
                ).getABIEncodedTransactionData();
 | 
			
		||||
            }
 | 
			
		||||
            if(isToETH){
 | 
			
		||||
                calldata = this._exchangeProxy.fillOtcOrderForEth(
 | 
			
		||||
                    otcOrdersData[0].order, otcOrdersData[0].signature, fillAmountPerOrder[0]
 | 
			
		||||
                ).getABIEncodedTransactionData();
 | 
			
		||||
            }
 | 
			
		||||
            else{
 | 
			
		||||
                calldata = this._exchangeProxy.fillOtcOrder(
 | 
			
		||||
                    otcOrdersData[0].order, otcOrdersData[0].signature, fillAmountPerOrder[0]
 | 
			
		||||
                ).getABIEncodedTransactionData();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (
 | 
			
		||||
                this.chainId === ChainId.Mainnet &&
 | 
			
		||||
                isMultiplexBatchFillCompatible(quote, optsWithDefaults)) {
 | 
			
		||||
                // return {
 | 
			
		||||
                //     calldataHexString: this._encodeMultiplexBatchFillCalldata(
 | 
			
		||||
                // ...
 | 
			
		||||
                // };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // if isToETH
 | 
			
		||||
            // encode for fillOtcOrderForEth
 | 
			
		||||
            // if isFromETH
 | 
			
		||||
            // encode for fillOtcOrderWithEth
 | 
			
		||||
            // else
 | 
			
		||||
            // fillOtcOrder
 | 
			
		||||
            // contracts/zero-ex/contracts/src/features/OtcOrdersFeature.sol
 | 
			
		||||
 | 
			
		||||
            // if more than 1 OTCOrder, bail and use the BatchMultiPlex encode below
 | 
			
		||||
        }
 | 
			
		||||
        if (this.chainId === ChainId.Mainnet && isMultiplexBatchFillCompatible(quote, optsWithDefaults)) {
 | 
			
		||||
            return {
 | 
			
		||||
                calldataHexString: this._encodeMultiplexBatchFillCalldata(
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import {
 | 
			
		||||
    LimitOrderFields,
 | 
			
		||||
    RfqOrder,
 | 
			
		||||
    RfqOrderFields,
 | 
			
		||||
    OtcOrderFields,
 | 
			
		||||
    Signature,
 | 
			
		||||
} from '@0x/protocol-utils';
 | 
			
		||||
import { TakerRequestQueryParamsUnnested, V4SignedRfqOrder } from '@0x/quote-server';
 | 
			
		||||
@@ -34,11 +35,11 @@ export interface OrderPrunerOpts {
 | 
			
		||||
 | 
			
		||||
export interface SignedOrder<T> {
 | 
			
		||||
    order: T;
 | 
			
		||||
    type: FillQuoteTransformerOrderType.Limit | FillQuoteTransformerOrderType.Rfq;
 | 
			
		||||
    type: FillQuoteTransformerOrderType.Limit | FillQuoteTransformerOrderType.Rfq | FillQuoteTransformerOrderType.Otc;
 | 
			
		||||
    signature: Signature;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type SignedNativeOrder = SignedOrder<LimitOrderFields> | SignedOrder<RfqOrderFields>;
 | 
			
		||||
export type SignedNativeOrder = SignedOrder<LimitOrderFields> | SignedOrder<RfqOrderFields> | SignedOrder<OtcOrderFields>;
 | 
			
		||||
export type NativeOrderWithFillableAmounts = SignedNativeOrder & NativeOrderFillableAmountFields;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { RfqOrder, Signature } from '@0x/protocol-utils';
 | 
			
		||||
import { OtcOrder, RfqOrder, Signature } from '@0x/protocol-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import { AltRfqMakerAssetOfferings } from '../types';
 | 
			
		||||
@@ -43,6 +43,48 @@ export interface RfqClientV1QuoteResponse {
 | 
			
		||||
    quotes: RfqClientV1Quote[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RfqClientV2PriceRequest {
 | 
			
		||||
    assetFillAmount: BigNumber;
 | 
			
		||||
    chainId: number;
 | 
			
		||||
    comparisonPrice: BigNumber | undefined;
 | 
			
		||||
    integratorId: string;
 | 
			
		||||
    intentOnFilling: boolean;
 | 
			
		||||
    makerToken: string;
 | 
			
		||||
    marketOperation: 'Sell' | 'Buy';
 | 
			
		||||
    takerAddress: string;
 | 
			
		||||
    takerToken: string;
 | 
			
		||||
    txOrigin: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RfqClientV2QuoteRequest extends RfqClientV2PriceRequest {}
 | 
			
		||||
 | 
			
		||||
export interface RfqClientV2Price {
 | 
			
		||||
    expiry: BigNumber;
 | 
			
		||||
    maker: string;
 | 
			
		||||
    makerAmount: BigNumber;
 | 
			
		||||
    makerToken: string;
 | 
			
		||||
    makerUri: string;
 | 
			
		||||
    takerAmount: BigNumber;
 | 
			
		||||
    takerToken: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RfqClientV2PriceResponse {
 | 
			
		||||
    prices: RfqClientV2Price[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RfqClientV2Quote {
 | 
			
		||||
    makerUri: string;
 | 
			
		||||
    order: OtcOrder;
 | 
			
		||||
    signature: Signature;
 | 
			
		||||
    fillableMakerAmount: BigNumber;
 | 
			
		||||
    fillableTakerAmount: BigNumber;
 | 
			
		||||
    fillableTakerFeeAmount: BigNumber;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RfqClientV2QuoteResponse {
 | 
			
		||||
    quotes: RfqClientV2Quote[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * IRfqClient is an interface that defines how to connect with an Rfq system.
 | 
			
		||||
 */
 | 
			
		||||
@@ -56,4 +98,14 @@ export interface IRfqClient {
 | 
			
		||||
     * Fetches a list of "firm quotes" or signed quotes from a remote Rfq server.
 | 
			
		||||
     */
 | 
			
		||||
    getV1QuotesAsync(request: RfqClientV1QuoteRequest): Promise<RfqClientV1QuoteResponse>;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Fetches a list of "v2 indicative quotes" or prices from a remote Rfq server
 | 
			
		||||
     */
 | 
			
		||||
    getV2PricesAsync(request: RfqClientV2PriceRequest): Promise<RfqClientV2PriceResponse>;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Fetches a list of "v2 firm quotes" or signed quotes from a remote Rfq server.
 | 
			
		||||
     */
 | 
			
		||||
    getV2QuotesAsync(request: RfqClientV2QuoteRequest): Promise<RfqClientV2QuoteResponse>;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -641,6 +641,7 @@ export const OPTIMISM_TOKENS = {
 | 
			
		||||
    WBTC: '0x68f180fcce6836688e9084f035309e29bf0a2095',
 | 
			
		||||
    nETH: '0x809dc529f07651bd43a172e8db6f4a7a0d771036',
 | 
			
		||||
    sWETH: '0x121ab82b49b2bc4c7901ca46b8277962b4350204',
 | 
			
		||||
    nUSD: '0x67C10C397dD0Ba417329543c1a40eb48AAa7cd00',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const CURVE_POOLS = {
 | 
			
		||||
@@ -770,6 +771,7 @@ export const SYNAPSE_MAINNET_POOLS = {
 | 
			
		||||
 | 
			
		||||
export const SYNAPSE_OPTIMISM_POOLS = {
 | 
			
		||||
    nETHLP: '0xe27bff97ce92c3e1ff7aa9f86781fdd6d48f5ee9',
 | 
			
		||||
    nUSDLP: '0xF44938b0125A6662f9536281aD2CD6c499F22004',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const SYNAPSE_BSC_POOLS = {
 | 
			
		||||
@@ -783,6 +785,7 @@ export const SYNAPSE_POLYGON_POOLS = {
 | 
			
		||||
export const SYNAPSE_FANTOM_POOLS = {
 | 
			
		||||
    nUSDLP: '0x2913e812cf0dcca30fb28e6cac3d2dcff4497688',
 | 
			
		||||
    nETHLP: '0x8d9ba570d6cb60c7e3e0f31343efe75ab8e65fb1',
 | 
			
		||||
    fUSDTLP: '0x85662fd123280827e11c59973ac9fcbe838dc3b4',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const SYNAPSE_AVALANCHE_POOLS = {
 | 
			
		||||
@@ -1654,6 +1657,24 @@ export const SYNAPSE_FANTOM_INFOS: { [name: string]: CurveInfo } = {
 | 
			
		||||
        metaTokens: undefined,
 | 
			
		||||
        gasSchedule: 140e3,
 | 
			
		||||
    },
 | 
			
		||||
    [SYNAPSE_FANTOM_POOLS.fUSDTLP]: {
 | 
			
		||||
        exchangeFunctionSelector: CurveFunctionSelectors.swap,
 | 
			
		||||
        sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
 | 
			
		||||
        buyQuoteFunctionSelector: CurveFunctionSelectors.None,
 | 
			
		||||
        poolAddress: SYNAPSE_FANTOM_POOLS.fUSDTLP,
 | 
			
		||||
        tokens: [FANTOM_TOKENS.USDC, FANTOM_TOKENS.fUSDT, FANTOM_TOKENS.nUSD],
 | 
			
		||||
        metaTokens: undefined,
 | 
			
		||||
        gasSchedule: 140e3,
 | 
			
		||||
    },
 | 
			
		||||
    [SYNAPSE_FANTOM_POOLS.nETHLP]: {
 | 
			
		||||
        exchangeFunctionSelector: CurveFunctionSelectors.swap,
 | 
			
		||||
        sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
 | 
			
		||||
        buyQuoteFunctionSelector: CurveFunctionSelectors.None,
 | 
			
		||||
        poolAddress: SYNAPSE_FANTOM_POOLS.nETHLP,
 | 
			
		||||
        tokens: [FANTOM_TOKENS.WETH, FANTOM_TOKENS.nETH],
 | 
			
		||||
        metaTokens: undefined,
 | 
			
		||||
        gasSchedule: 140e3,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const SYNAPSE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
 | 
			
		||||
@@ -1678,6 +1699,15 @@ export const SYNAPSE_OPTIMISM_INFOS: { [name: string]: CurveInfo } = {
 | 
			
		||||
        metaTokens: undefined,
 | 
			
		||||
        gasSchedule: 140e3,
 | 
			
		||||
    },
 | 
			
		||||
    [SYNAPSE_OPTIMISM_POOLS.nUSDLP]: {
 | 
			
		||||
        exchangeFunctionSelector: CurveFunctionSelectors.swap,
 | 
			
		||||
        sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
 | 
			
		||||
        buyQuoteFunctionSelector: CurveFunctionSelectors.None,
 | 
			
		||||
        poolAddress: SYNAPSE_OPTIMISM_POOLS.nUSDLP,
 | 
			
		||||
        tokens: [OPTIMISM_TOKENS.nUSD, OPTIMISM_TOKENS.USDC],
 | 
			
		||||
        metaTokens: undefined,
 | 
			
		||||
        gasSchedule: 140e3,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const SYNAPSE_POLYGON_INFOS: { [name: string]: CurveInfo } = {
 | 
			
		||||
 
 | 
			
		||||
@@ -747,6 +747,26 @@ export class MarketOperationUtils {
 | 
			
		||||
                              wholeOrderPrice,
 | 
			
		||||
                              rfqt,
 | 
			
		||||
                          );
 | 
			
		||||
 | 
			
		||||
                const otcQuotes = await rfqt.rfqClient?.getV2QuotesAsync({
 | 
			
		||||
                    assetFillAmount: amount,
 | 
			
		||||
                    chainId: this._sampler.chainId,
 | 
			
		||||
                    integratorId: rfqt.integrator.integratorId,
 | 
			
		||||
                    intentOnFilling: rfqt.intentOnFilling,
 | 
			
		||||
                    makerToken,
 | 
			
		||||
                    marketOperation: side,
 | 
			
		||||
                    takerAddress: rfqt.takerAddress,
 | 
			
		||||
                    takerToken,
 | 
			
		||||
                    txOrigin: rfqt.txOrigin,
 | 
			
		||||
                });
 | 
			
		||||
                const otcQuotesWithFillableAmounts: NativeOrderWithFillableAmounts[] =
 | 
			
		||||
                    otcQuotes === undefined
 | 
			
		||||
                        ? []
 | 
			
		||||
                        : otcQuotes.quotes.map(q => ({
 | 
			
		||||
                              ...q,
 | 
			
		||||
                              type: FillQuoteTransformerOrderType.Otc,
 | 
			
		||||
                          }));
 | 
			
		||||
 | 
			
		||||
                const deltaTime = new Date().getTime() - timeStart;
 | 
			
		||||
                DEFAULT_INFO_LOGGER({
 | 
			
		||||
                    rfqQuoteType: 'firm',
 | 
			
		||||
@@ -777,6 +797,7 @@ export class MarketOperationUtils {
 | 
			
		||||
                    );
 | 
			
		||||
                    marketSideLiquidity.quotes.nativeOrders = [
 | 
			
		||||
                        ...quotesWithOrderFillableAmounts,
 | 
			
		||||
                        ...otcQuotesWithFillableAmounts,
 | 
			
		||||
                        ...marketSideLiquidity.quotes.nativeOrders,
 | 
			
		||||
                    ];
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ import {
 | 
			
		||||
    FillQuoteTransformerLimitOrderInfo,
 | 
			
		||||
    FillQuoteTransformerOrderType,
 | 
			
		||||
    FillQuoteTransformerRfqOrderInfo,
 | 
			
		||||
    FillQuoteTransformerOtcOrderInfo
 | 
			
		||||
} from '@0x/protocol-utils';
 | 
			
		||||
import { MarketOperation } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
@@ -195,7 +196,9 @@ export interface FillData {}
 | 
			
		||||
// `FillData` for native fills. Represents a single native order
 | 
			
		||||
export type NativeRfqOrderFillData = FillQuoteTransformerRfqOrderInfo;
 | 
			
		||||
export type NativeLimitOrderFillData = FillQuoteTransformerLimitOrderInfo;
 | 
			
		||||
export type NativeFillData = NativeRfqOrderFillData | NativeLimitOrderFillData;
 | 
			
		||||
export type NativeOtcOrderFillData = FillQuoteTransformerOtcOrderInfo;
 | 
			
		||||
export type NativeFillData = NativeRfqOrderFillData | NativeLimitOrderFillData | NativeOtcOrderFillData;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Represents an individual DEX sample from the sampler contract
 | 
			
		||||
export interface DexSample<TFillData extends FillData = FillData> {
 | 
			
		||||
@@ -454,13 +457,19 @@ export interface OptimizedRfqOrder extends OptimizedMarketOrderBase<NativeRfqOrd
 | 
			
		||||
    fillData: NativeRfqOrderFillData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface OptimizedOtcOrder extends OptimizedMarketOrderBase<NativeOtcOrderFillData> {
 | 
			
		||||
    type: FillQuoteTransformerOrderType.Otc;
 | 
			
		||||
    fillData: NativeOtcOrderFillData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Optimized orders to fill.
 | 
			
		||||
 */
 | 
			
		||||
export type OptimizedMarketOrder =
 | 
			
		||||
    | OptimizedMarketBridgeOrder<FillData>
 | 
			
		||||
    | OptimizedMarketOrderBase<NativeLimitOrderFillData>
 | 
			
		||||
    | OptimizedMarketOrderBase<NativeRfqOrderFillData>;
 | 
			
		||||
    | OptimizedMarketOrderBase<NativeRfqOrderFillData>
 | 
			
		||||
    | OptimizedMarketOrderBase<NativeOtcOrderFillData>;
 | 
			
		||||
 | 
			
		||||
export interface GetMarketOrdersRfqOpts extends RfqRequestOpts {
 | 
			
		||||
    rfqClient?: IRfqClient;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import {
 | 
			
		||||
    NativeCollapsedFill,
 | 
			
		||||
    NativeFillData,
 | 
			
		||||
    NativeLimitOrderFillData,
 | 
			
		||||
    NativeOtcOrderFillData,
 | 
			
		||||
    NativeRfqOrderFillData,
 | 
			
		||||
    RawQuotes,
 | 
			
		||||
} from './market_operation_utils/types';
 | 
			
		||||
@@ -353,7 +354,7 @@ function _isNativeOrderFromCollapsedFill(cf: CollapsedFill): cf is NativeCollaps
 | 
			
		||||
 */
 | 
			
		||||
export function nativeOrderToReportEntry(
 | 
			
		||||
    type: FillQuoteTransformerOrderType,
 | 
			
		||||
    fillData: NativeLimitOrderFillData | NativeRfqOrderFillData,
 | 
			
		||||
    fillData: NativeLimitOrderFillData | NativeRfqOrderFillData | NativeOtcOrderFillData,
 | 
			
		||||
    fillableAmount: BigNumber,
 | 
			
		||||
    comparisonPrice?: BigNumber | undefined,
 | 
			
		||||
    quoteRequestor?: QuoteRequestor,
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/assert": "^3.0.34",
 | 
			
		||||
        "@0x/contract-addresses": "^6.14.0",
 | 
			
		||||
        "@0x/contract-addresses": "^6.16.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.20.2",
 | 
			
		||||
        "@0x/json-schemas": "^6.4.4",
 | 
			
		||||
        "@0x/subproviders": "^6.6.5",
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@ export type LimitOrderFields = typeof LIMIT_ORDER_DEFAULT_VALUES;
 | 
			
		||||
export type RfqOrderFields = typeof RFQ_ORDER_DEFAULT_VALUES;
 | 
			
		||||
export type OtcOrderFields = typeof OTC_ORDER_DEFAULT_VALUES;
 | 
			
		||||
export type BridgeOrderFields = typeof BRIDGE_ORDER_DEFAULT_VALUES;
 | 
			
		||||
export type NativeOrder = RfqOrder | LimitOrder;
 | 
			
		||||
export type NativeOrder = RfqOrder | LimitOrder | OtcOrder;
 | 
			
		||||
 | 
			
		||||
export enum OrderStatus {
 | 
			
		||||
    Invalid = 0,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import { AbiEncoder, BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
 | 
			
		||||
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';
 | 
			
		||||
 | 
			
		||||
const BRIDGE_ORDER_ABI_COMPONENTS = [
 | 
			
		||||
@@ -39,6 +39,20 @@ const RFQ_ORDER_INFO_ABI_COMPONENTS = [
 | 
			
		||||
    { 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`
 | 
			
		||||
 */
 | 
			
		||||
@@ -65,6 +79,11 @@ export const fillQuoteTransformerDataEncoder = AbiEncoder.create([
 | 
			
		||||
                type: 'tuple[]',
 | 
			
		||||
                components: RFQ_ORDER_INFO_ABI_COMPONENTS,
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                name: 'otcOrders',
 | 
			
		||||
                type: 'tuple[]',
 | 
			
		||||
                components: OTC_ORDER_INFO_ABI_COMPONENTS,
 | 
			
		||||
            },
 | 
			
		||||
            { name: 'fillSequence', type: 'uint8[]' },
 | 
			
		||||
            { name: 'fillAmount', type: 'uint256' },
 | 
			
		||||
            { name: 'refundReceiver', type: 'address' },
 | 
			
		||||
@@ -87,6 +106,7 @@ export enum FillQuoteTransformerOrderType {
 | 
			
		||||
    Bridge,
 | 
			
		||||
    Limit,
 | 
			
		||||
    Rfq,
 | 
			
		||||
    Otc,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -170,6 +190,11 @@ export type FillQuoteTransformerLimitOrderInfo = FillQuoteTransformerNativeOrder
 | 
			
		||||
 */
 | 
			
		||||
export type FillQuoteTransformerRfqOrderInfo = FillQuoteTransformerNativeOrderInfo<RfqOrderFields>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * `FillQuoteTransformer.OtcOrderInfo`
 | 
			
		||||
 */
 | 
			
		||||
 export type FillQuoteTransformerOtcOrderInfo = FillQuoteTransformerNativeOrderInfo<OtcOrderFields>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ABI-encode a `FillQuoteTransformer.TransformData` type.
 | 
			
		||||
 */
 | 
			
		||||
@@ -177,6 +202,8 @@ export function encodeFillQuoteTransformerData(data: FillQuoteTransformerData):
 | 
			
		||||
    return fillQuoteTransformerDataEncoder.encode([data]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ABI-decode a `FillQuoteTransformer.TransformData` type.
 | 
			
		||||
 */
 | 
			
		||||
@@ -184,6 +211,7 @@ export function decodeFillQuoteTransformerData(encoded: string): FillQuoteTransf
 | 
			
		||||
    return fillQuoteTransformerDataEncoder.decode(encoded).data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ABI encoder for `WethTransformer.TransformData`
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { expect } from 'chai';
 | 
			
		||||
import * as ethjs from 'ethereumjs-util';
 | 
			
		||||
 | 
			
		||||
import { LimitOrder, RfqOrder } from '../src/orders';
 | 
			
		||||
import { LimitOrder, OtcOrder, RfqOrder } from '../src/orders';
 | 
			
		||||
import { SignatureType } from '../src/signature_utils';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
@@ -145,4 +145,64 @@ describe('orders', () => {
 | 
			
		||||
            expect(actual).to.deep.eq(expected);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('OtcOrder', () => {
 | 
			
		||||
        const order = new OtcOrder({
 | 
			
		||||
            makerToken: '0x349e8d89e8b37214d9ce3949fc5754152c525bc3',
 | 
			
		||||
            takerToken: '0x83c62b2e67dea0df2a27be0def7a22bd7102642c',
 | 
			
		||||
            makerAmount: new BigNumber(1234),
 | 
			
		||||
            takerAmount: new BigNumber(5678),
 | 
			
		||||
            maker: '0x8d5e5b5b5d187bdce2e0143eb6b3cc44eef3c0cb',
 | 
			
		||||
            taker: '0x615312fb74c31303eab07dea520019bb23f4c6c2',
 | 
			
		||||
            txOrigin: '0x70f2d6c7acd257a6700d745b76c602ceefeb8e20',
 | 
			
		||||
            expiryAndNonce: new BigNumber(1001),
 | 
			
		||||
            chainId: 8008,
 | 
			
		||||
            verifyingContract: '0x6701704d2421c64ee9aa93ec7f96ede81c4be77d',
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can get the struct hash', () => {
 | 
			
		||||
            const actual = order.getStructHash();
 | 
			
		||||
            // const expected = '0x995b6261fa93cd5acd5121f404305f8e9f9c388723f3e53fb05bd5eb534b4899';
 | 
			
		||||
            // expect(actual).to.eq(expected);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can get the EIP712 hash', () => {
 | 
			
		||||
            const actual = order.getHash();
 | 
			
		||||
            // const expected = '0xb4c40524740dcc4030a62b6d9afe740f6ca24508e59ef0c5bd99d5649a430885';
 | 
			
		||||
            // expect(actual).to.deep.eq(expected);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can get an EthSign signature with a provider', async () => {
 | 
			
		||||
            const actual = await order.clone({ maker: providerMaker }).getSignatureWithProviderAsync(provider);
 | 
			
		||||
            // const expected = {
 | 
			
		||||
            //     signatureType: SignatureType.EthSign,
 | 
			
		||||
            //     r: '0xed555259efe38e2d679f7bc18385e51ce158576ced6c11630f67ba37b3e59a29',
 | 
			
		||||
            //     s: '0x769211cf3e86b254e3755e1dcf459f5b362ca1c42ec3cf08841d90cb44f2a8e4',
 | 
			
		||||
            //     v: 27,
 | 
			
		||||
            // };
 | 
			
		||||
            // expect(actual).to.deep.eq(expected);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can get an EthSign signature with a private key', () => {
 | 
			
		||||
            const actual = order.clone({ maker: keyMaker }).getSignatureWithKey(key);
 | 
			
		||||
            // const expected = {
 | 
			
		||||
            //     signatureType: SignatureType.EthSign,
 | 
			
		||||
            //     r: '0xba231f67168d6d1fd2b83e0a3a6b1663ec493b98a8dbe34689c8e8171972522f',
 | 
			
		||||
            //     s: '0x47023a5f73b5f638e9a138de26b35e59847680bee78af0c8251de532e7c39d8b',
 | 
			
		||||
            //     v: 28,
 | 
			
		||||
            // };
 | 
			
		||||
            // expect(actual).to.deep.eq(expected);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can get an EIP712 signature with a private key', () => {
 | 
			
		||||
            const actual = order.clone({ maker: keyMaker }).getSignatureWithKey(key, SignatureType.EIP712);
 | 
			
		||||
            // const expected = {
 | 
			
		||||
            //     signatureType: SignatureType.EIP712,
 | 
			
		||||
            //     r: '0x824d70ae7cccea382ddd51f773f9745abb928dadbccebbd090ca371d7b8fb741',
 | 
			
		||||
            //     s: '0x7557a009f7cfa207d19a8fd42950458340de718a7b35522051cde6f75ad42cba',
 | 
			
		||||
            //     v: 27,
 | 
			
		||||
            // };
 | 
			
		||||
            // expect(actual).to.deep.eq(expected);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								yarn.lock
									
									
									
									
									
								
							@@ -732,6 +732,26 @@
 | 
			
		||||
    js-sha3 "^0.7.0"
 | 
			
		||||
    uuid "^3.3.2"
 | 
			
		||||
 | 
			
		||||
"@0x/contract-addresses@^6.16.0":
 | 
			
		||||
  version "6.16.0"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@0x/contract-addresses/-/contract-addresses-6.16.0.tgz#dc8dc4c5319f7eee40e10ccb462a254b6eb03b14"
 | 
			
		||||
  integrity sha512-Gsc/9EttCUtemiJR5/U1JPezxVUtlQ3pq6rPkc7YJL0isK0AwYIrQm82b6Z8wyg9bPMs9dkONc806nnUehY5pQ==
 | 
			
		||||
 | 
			
		||||
"@0x/contract-wrappers@^13.20.4":
 | 
			
		||||
  version "13.20.4"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@0x/contract-wrappers/-/contract-wrappers-13.20.4.tgz#e77e6bc4be2c0288fe6846cf7408a1694567e7e2"
 | 
			
		||||
  integrity sha512-kbaYHjjgx1MN2+JRipmo6crl8p4lZpFyVFFp2ULtcEFBEzi0UIEMxo7SXCEguMe/yOY7NGGuLUMJ3Zd3IEjCxA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@0x/assert" "^3.0.34"
 | 
			
		||||
    "@0x/base-contract" "^6.5.0"
 | 
			
		||||
    "@0x/contract-addresses" "^6.16.0"
 | 
			
		||||
    "@0x/json-schemas" "^6.4.4"
 | 
			
		||||
    "@0x/types" "^3.3.6"
 | 
			
		||||
    "@0x/utils" "^6.5.3"
 | 
			
		||||
    "@0x/web3-wrapper" "^7.6.5"
 | 
			
		||||
    ethereum-types "^3.7.0"
 | 
			
		||||
    ethers "~4.0.4"
 | 
			
		||||
 | 
			
		||||
"@0x/contracts-asset-proxy@^3.7.19":
 | 
			
		||||
  version "3.7.19"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@0x/contracts-asset-proxy/-/contracts-asset-proxy-3.7.19.tgz#ee621a233f4d77b439c74c5b8d70db2e1ed001c4"
 | 
			
		||||
@@ -783,6 +803,14 @@
 | 
			
		||||
    "@0x/web3-wrapper" "^7.5.3"
 | 
			
		||||
    lodash "^4.17.11"
 | 
			
		||||
 | 
			
		||||
"@0x/contracts-erc20@^3.3.32":
 | 
			
		||||
  version "3.3.32"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@0x/contracts-erc20/-/contracts-erc20-3.3.32.tgz#e389594fe66722f4ad05ef9f5ebc581f35ea3fb2"
 | 
			
		||||
  integrity sha512-SK2vAyXxDU4HsEB0rjC2/NQJadournmw7VksofY1GxbGYdHPcp2VHdGAbbncCGRW56DByS89RVphH9JIsy5Fhg==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@0x/base-contract" "^6.5.0"
 | 
			
		||||
    ethers "~4.0.4"
 | 
			
		||||
 | 
			
		||||
"@0x/contracts-erc721@^3.1.37":
 | 
			
		||||
  version "3.1.37"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@0x/contracts-erc721/-/contracts-erc721-3.1.37.tgz#d7d356737e3d2752cf49be385237fbf7d0c5745c"
 | 
			
		||||
@@ -867,6 +895,55 @@
 | 
			
		||||
    ethereum-types "^3.5.0"
 | 
			
		||||
    ethereumjs-util "^7.0.10"
 | 
			
		||||
 | 
			
		||||
"@0x/contracts-test-utils@^5.4.23":
 | 
			
		||||
  version "5.4.23"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@0x/contracts-test-utils/-/contracts-test-utils-5.4.23.tgz#515e120646cbba6644fa7c67b3259736b6c88601"
 | 
			
		||||
  integrity sha512-cmLalK8MV3OEzbLq9Jyfc0a13//rR6bVQXtbYCNwb/ygqsP6HOCPQ24T6PLS6JyGb/nPCl2TRrrZ9TDgNb2uOA==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@0x/assert" "^3.0.34"
 | 
			
		||||
    "@0x/base-contract" "^6.5.0"
 | 
			
		||||
    "@0x/contract-addresses" "^6.16.0"
 | 
			
		||||
    "@0x/dev-utils" "^4.2.14"
 | 
			
		||||
    "@0x/json-schemas" "^6.4.4"
 | 
			
		||||
    "@0x/order-utils" "^10.4.28"
 | 
			
		||||
    "@0x/sol-coverage" "^4.0.45"
 | 
			
		||||
    "@0x/sol-profiler" "^4.1.35"
 | 
			
		||||
    "@0x/sol-trace" "^3.0.45"
 | 
			
		||||
    "@0x/subproviders" "^6.6.5"
 | 
			
		||||
    "@0x/types" "^3.3.6"
 | 
			
		||||
    "@0x/typescript-typings" "^5.3.1"
 | 
			
		||||
    "@0x/utils" "^6.5.3"
 | 
			
		||||
    "@0x/web3-wrapper" "^7.6.5"
 | 
			
		||||
    "@types/bn.js" "^4.11.0"
 | 
			
		||||
    "@types/js-combinatorics" "^0.5.29"
 | 
			
		||||
    "@types/lodash" "4.14.104"
 | 
			
		||||
    "@types/mocha" "^5.2.7"
 | 
			
		||||
    "@types/node" "12.12.54"
 | 
			
		||||
    bn.js "^4.11.8"
 | 
			
		||||
    chai "^4.0.1"
 | 
			
		||||
    chai-as-promised "^7.1.0"
 | 
			
		||||
    chai-bignumber "^3.0.0"
 | 
			
		||||
    decimal.js "^10.2.0"
 | 
			
		||||
    dirty-chai "^2.0.1"
 | 
			
		||||
    ethereum-types "^3.7.0"
 | 
			
		||||
    ethereumjs-util "^7.0.10"
 | 
			
		||||
    ethers "~4.0.4"
 | 
			
		||||
    js-combinatorics "^0.5.3"
 | 
			
		||||
    lodash "^4.17.11"
 | 
			
		||||
    make-promises-safe "^1.1.0"
 | 
			
		||||
    mocha "^6.2.0"
 | 
			
		||||
 | 
			
		||||
"@0x/contracts-utils@^4.8.12":
 | 
			
		||||
  version "4.8.12"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@0x/contracts-utils/-/contracts-utils-4.8.12.tgz#849c2f2f9368a4041c2e2d0c0c0c9716a13383ca"
 | 
			
		||||
  integrity sha512-CWKBAFcs4dyD33McswwJEsoFwldJc0onLFQyLLpd2rAOlwoWxW6QuvGmtE5LOXOXsTy11kDJTO68dQylIN6Qlw==
 | 
			
		||||
  dependencies:
 | 
			
		||||
    "@0x/base-contract" "^6.5.0"
 | 
			
		||||
    "@0x/typescript-typings" "^5.3.1"
 | 
			
		||||
    "@0x/utils" "^6.5.3"
 | 
			
		||||
    bn.js "^4.11.8"
 | 
			
		||||
    ethereum-types "^3.7.0"
 | 
			
		||||
 | 
			
		||||
"@0x/dev-utils@^4.2.14":
 | 
			
		||||
  version "4.2.14"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/@0x/dev-utils/-/dev-utils-4.2.14.tgz#2b15b3247ccaf111d8d42689907b603537b0a86c"
 | 
			
		||||
@@ -3796,6 +3873,7 @@ bigi@1.4.2, bigi@^1.1.0:
 | 
			
		||||
bignumber.js@7.2.1, bignumber.js@^9.0.0, bignumber.js@^9.0.2, bignumber.js@~4.1.0, bignumber.js@~9.0.0, bignumber.js@~9.0.2:
 | 
			
		||||
  version "9.0.2"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673"
 | 
			
		||||
  integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==
 | 
			
		||||
 | 
			
		||||
binary-extensions@^2.0.0:
 | 
			
		||||
  version "2.1.0"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user