@0x:contracts-exchange Added protocol fees to fillOrders and matchOrders
				
					
				
			This commit is contained in:
		@@ -52,12 +52,10 @@ library LibFillResults {
 | 
			
		||||
    /// @dev Calculates amounts filled and fees paid by maker and taker.
 | 
			
		||||
    /// @param order to be filled.
 | 
			
		||||
    /// @param takerAssetFilledAmount Amount of takerAsset that will be filled.
 | 
			
		||||
    /// @param protocolFeeMultiplier The multiplier used to calculate protocol fees.
 | 
			
		||||
    /// @return fillResults Amounts filled and fees paid by maker and taker.
 | 
			
		||||
    function calculateFillResults(
 | 
			
		||||
        LibOrder.Order memory order,
 | 
			
		||||
        uint256 takerAssetFilledAmount,
 | 
			
		||||
        uint256 protocolFeeMultiplier
 | 
			
		||||
        uint256 takerAssetFilledAmount
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        view
 | 
			
		||||
@@ -81,9 +79,6 @@ library LibFillResults {
 | 
			
		||||
            order.takerFee
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Compute the protocol fee for a single fill.
 | 
			
		||||
        fillResults.protocolFeePaid = tx.gasprice.safeMul(protocolFeeMultiplier);
 | 
			
		||||
 | 
			
		||||
        return fillResults;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -95,7 +90,6 @@ library LibFillResults {
 | 
			
		||||
    /// @param rightOrder Second order to match.
 | 
			
		||||
    /// @param leftOrderTakerAssetFilledAmount Amount of left order already filled.
 | 
			
		||||
    /// @param rightOrderTakerAssetFilledAmount Amount of right order already filled.
 | 
			
		||||
    /// @param protocolFeeMultiplier The multiplier used to calculate protocol fees.
 | 
			
		||||
    /// @param shouldMaximallyFillOrders A value that indicates whether or not this calculation should use
 | 
			
		||||
    ///                                  the maximal fill order matching strategy.
 | 
			
		||||
    /// @param matchedFillResults Amounts to fill and fees to pay by maker and taker of matched orders.
 | 
			
		||||
@@ -104,7 +98,6 @@ library LibFillResults {
 | 
			
		||||
        LibOrder.Order memory rightOrder,
 | 
			
		||||
        uint256 leftOrderTakerAssetFilledAmount,
 | 
			
		||||
        uint256 rightOrderTakerAssetFilledAmount,
 | 
			
		||||
        uint256 protocolFeeMultiplier,
 | 
			
		||||
        bool shouldMaximallyFillOrders
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
@@ -170,11 +163,6 @@ library LibFillResults {
 | 
			
		||||
            rightOrder.takerFee
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Compute the protocol fees
 | 
			
		||||
        uint256 protocolFee = tx.gasprice.safeMul(protocolFeeMultiplier);
 | 
			
		||||
        matchedFillResults.left.protocolFeePaid = protocolFee;
 | 
			
		||||
        matchedFillResults.right.protocolFeePaid = protocolFee;
 | 
			
		||||
 | 
			
		||||
        // Return fill results
 | 
			
		||||
        return matchedFillResults;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -29,14 +29,13 @@ contract TestLibFillResults {
 | 
			
		||||
 | 
			
		||||
    function calculateFillResults(
 | 
			
		||||
        LibOrder.Order memory order,
 | 
			
		||||
        uint256 takerAssetFilledAmount,
 | 
			
		||||
        uint256 protocolFeeMultiplier
 | 
			
		||||
        uint256 takerAssetFilledAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (LibFillResults.FillResults memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        fillResults = LibFillResults.calculateFillResults(order, takerAssetFilledAmount, protocolFeeMultiplier);
 | 
			
		||||
        fillResults = LibFillResults.calculateFillResults(order, takerAssetFilledAmount);
 | 
			
		||||
        return fillResults;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -45,7 +44,6 @@ contract TestLibFillResults {
 | 
			
		||||
        LibOrder.Order memory rightOrder,
 | 
			
		||||
        uint256 leftOrderTakerAssetFilledAmount,
 | 
			
		||||
        uint256 rightOrderTakerAssetFilledAmount,
 | 
			
		||||
        uint256 protocolFeeMultiplier,
 | 
			
		||||
        bool shouldMaximallyFillOrders
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
@@ -57,7 +55,6 @@ contract TestLibFillResults {
 | 
			
		||||
            rightOrder,
 | 
			
		||||
            leftOrderTakerAssetFilledAmount,
 | 
			
		||||
            rightOrderTakerAssetFilledAmount,
 | 
			
		||||
            protocolFeeMultiplier,
 | 
			
		||||
            shouldMaximallyFillOrders
 | 
			
		||||
        );
 | 
			
		||||
        return matchedFillResults;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
        "evmVersion": "constantinople",
 | 
			
		||||
        "optimizer": {
 | 
			
		||||
            "enabled": true,
 | 
			
		||||
            "runs": 1000000,
 | 
			
		||||
            "runs": 15000,
 | 
			
		||||
            "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
 | 
			
		||||
        },
 | 
			
		||||
        "outputSelection": {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../src/interfaces/IExchange.sol";
 | 
			
		||||
@@ -89,7 +89,7 @@ contract ExchangeWrapper is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
    {
 | 
			
		||||
        address takerAddress = msg.sender;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.5;
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../src/interfaces/IExchange.sol";
 | 
			
		||||
@@ -104,7 +104,7 @@ contract Whitelist is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
    {
 | 
			
		||||
        address takerAddress = msg.sender;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -35,12 +35,12 @@ import "./MixinSignatureValidator.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract MixinExchangeCore is
 | 
			
		||||
    IExchangeCore,
 | 
			
		||||
    Refundable,
 | 
			
		||||
    LibEIP712ExchangeDomain,
 | 
			
		||||
    IExchangeCore,
 | 
			
		||||
    MixinAssetProxyDispatcher,
 | 
			
		||||
    MixinSignatureValidator,
 | 
			
		||||
    MixinProtocolFees
 | 
			
		||||
    MixinProtocolFees,
 | 
			
		||||
    MixinSignatureValidator
 | 
			
		||||
{
 | 
			
		||||
    using LibOrder for LibOrder.Order;
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
@@ -103,7 +103,7 @@ contract MixinExchangeCore is
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        nonReentrant
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
        returns (LibFillResults.FillResults memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        fillResults = _fillOrder(
 | 
			
		||||
@@ -217,10 +217,18 @@ contract MixinExchangeCore is
 | 
			
		||||
        uint256 takerAssetFilledAmount = LibSafeMath.min256(takerAssetFillAmount, remainingTakerAssetAmount);
 | 
			
		||||
 | 
			
		||||
        // Compute proportional fill amounts
 | 
			
		||||
        fillResults = LibFillResults.calculateFillResults(order, takerAssetFilledAmount, protocolFeeMultiplier);
 | 
			
		||||
        fillResults = LibFillResults.calculateFillResults(order, takerAssetFilledAmount);
 | 
			
		||||
 | 
			
		||||
        bytes32 orderHash = orderInfo.orderHash;
 | 
			
		||||
 | 
			
		||||
        // Settle order
 | 
			
		||||
        _settleOrder(
 | 
			
		||||
            orderHash,
 | 
			
		||||
            order,
 | 
			
		||||
            takerAddress,
 | 
			
		||||
            fillResults
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Update exchange internal state
 | 
			
		||||
        _updateFilledState(
 | 
			
		||||
            order,
 | 
			
		||||
@@ -230,14 +238,6 @@ contract MixinExchangeCore is
 | 
			
		||||
            fillResults
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Settle order
 | 
			
		||||
        _settleOrder(
 | 
			
		||||
            orderHash,
 | 
			
		||||
            order,
 | 
			
		||||
            takerAddress,
 | 
			
		||||
            fillResults
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return fillResults;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -462,25 +462,26 @@ contract MixinExchangeCore is
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Transfer protocol fee -> staking if the fee should be paid
 | 
			
		||||
        if (staking != address(0)) {
 | 
			
		||||
            // If sufficient ether was sent to the contract, the protocol fee should be paid in ETH.
 | 
			
		||||
            // Otherwise the fee should be paid in WETH.
 | 
			
		||||
            uint256 protocolFee = fillResults.protocolFeePaid;
 | 
			
		||||
            if (address(this).balance >= protocolFee) {
 | 
			
		||||
                IStaking(staking).payProtocolFee.value(protocolFee)(order.makerAddress);
 | 
			
		||||
            } else {
 | 
			
		||||
                // Transfer the Weth
 | 
			
		||||
                _dispatchTransferFrom(
 | 
			
		||||
                    orderHash,
 | 
			
		||||
                    WETH_ASSET_DATA,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    staking,
 | 
			
		||||
                    protocolFee
 | 
			
		||||
                );
 | 
			
		||||
        address feeCollector = protocolFeeCollector;
 | 
			
		||||
        if (feeCollector != address(0)) {
 | 
			
		||||
            // Create a stack variable to hold the value that will be sent so that the gas optimization of
 | 
			
		||||
            // only having one call statement can be implemented.
 | 
			
		||||
            uint256 valuePaid = 0;
 | 
			
		||||
 | 
			
		||||
                // Attribute the protocol fee to the maker
 | 
			
		||||
                IStaking(staking).recordProtocolFee(order.makerAddress, protocolFee);
 | 
			
		||||
            // Calculate the protocol fee that should be paid and populate the `protocolFeePaid` field in `fillResults`.
 | 
			
		||||
            // It's worth noting that we leave this calculation until now so that work isn't wasted if a fee collector
 | 
			
		||||
            // is not registered in the exchange.
 | 
			
		||||
            uint256 protocolFee = tx.gasprice.safeMul(protocolFeeMultiplier);
 | 
			
		||||
            fillResults.protocolFeePaid = protocolFee;
 | 
			
		||||
 | 
			
		||||
            // If sufficient ether was sent to the contract, the protocol fee should be paid in ETH.
 | 
			
		||||
            // Otherwise the fee should be paid in WETH. Since the exchange doesn't actually handle
 | 
			
		||||
            // this case, it will just forward the procotolFee in ether in case 1 and will send zero
 | 
			
		||||
            // value in case 2.
 | 
			
		||||
            if (address(this).balance >= protocolFee) {
 | 
			
		||||
                valuePaid = protocolFee;
 | 
			
		||||
            }
 | 
			
		||||
            IStaking(feeCollector).payProtocolFee.value(valuePaid)(order.makerAddress, takerAddress, protocolFee);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ contract MixinMatchOrders is
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        nonReentrant
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
        returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults)
 | 
			
		||||
    {
 | 
			
		||||
        return _batchMatchOrders(
 | 
			
		||||
@@ -77,7 +77,7 @@ contract MixinMatchOrders is
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        nonReentrant
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
        returns (LibFillResults.BatchMatchedFillResults memory batchMatchedFillResults)
 | 
			
		||||
    {
 | 
			
		||||
        return _batchMatchOrders(
 | 
			
		||||
@@ -107,7 +107,7 @@ contract MixinMatchOrders is
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        nonReentrant
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
        returns (LibFillResults.MatchedFillResults memory matchedFillResults)
 | 
			
		||||
    {
 | 
			
		||||
        return _matchOrders(
 | 
			
		||||
@@ -137,7 +137,7 @@ contract MixinMatchOrders is
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        nonReentrant
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
        returns (LibFillResults.MatchedFillResults memory matchedFillResults)
 | 
			
		||||
    {
 | 
			
		||||
        return _matchOrders(
 | 
			
		||||
@@ -385,10 +385,19 @@ contract MixinMatchOrders is
 | 
			
		||||
            rightOrder,
 | 
			
		||||
            leftOrderInfo.orderTakerAssetFilledAmount,
 | 
			
		||||
            rightOrderInfo.orderTakerAssetFilledAmount,
 | 
			
		||||
            protocolFeeMultiplier,
 | 
			
		||||
            shouldMaximallyFillOrders
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Settle matched orders. Succeeds or throws.
 | 
			
		||||
        _settleMatchedOrders(
 | 
			
		||||
            leftOrderInfo.orderHash,
 | 
			
		||||
            rightOrderInfo.orderHash,
 | 
			
		||||
            leftOrder,
 | 
			
		||||
            rightOrder,
 | 
			
		||||
            takerAddress,
 | 
			
		||||
            matchedFillResults
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Update exchange state
 | 
			
		||||
        _updateFilledState(
 | 
			
		||||
            leftOrder,
 | 
			
		||||
@@ -405,16 +414,6 @@ contract MixinMatchOrders is
 | 
			
		||||
            matchedFillResults.right
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Settle matched orders. Succeeds or throws.
 | 
			
		||||
        _settleMatchedOrders(
 | 
			
		||||
            leftOrderInfo.orderHash,
 | 
			
		||||
            rightOrderInfo.orderHash,
 | 
			
		||||
            leftOrder,
 | 
			
		||||
            rightOrder,
 | 
			
		||||
            takerAddress,
 | 
			
		||||
            matchedFillResults
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return matchedFillResults;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -490,39 +489,27 @@ contract MixinMatchOrders is
 | 
			
		||||
            matchedFillResults.profitInRightMakerAsset
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Pay protocol fees
 | 
			
		||||
        if (staking != address(0)) {
 | 
			
		||||
            // matchedFillResults.left.protocolFeePaid == matchedFillResults.right.protocolFeePaid
 | 
			
		||||
            // so we only use matchedFillResults.left.protocolFeePaid as a gas optimization.
 | 
			
		||||
            uint256 protocolFee = matchedFillResults.left.protocolFeePaid;
 | 
			
		||||
        // Pay the protocol fees if there is a registered `protocolFeeCollector` address.
 | 
			
		||||
        address feeCollector = protocolFeeCollector;
 | 
			
		||||
        if (feeCollector != address(0)) {
 | 
			
		||||
            // Calculate the protocol fee that should be paid and populate the `protocolFeePaid` field in the left and
 | 
			
		||||
            // right `fillResults` of `matchedFillResults`. It's worth noting that we leave this calculation until now
 | 
			
		||||
            // so that work isn't wasted if a fee collector is not registered in the exchange.
 | 
			
		||||
            uint256 protocolFee = tx.gasprice.safeMul(protocolFeeMultiplier);
 | 
			
		||||
            matchedFillResults.left.protocolFeePaid = protocolFee;
 | 
			
		||||
            matchedFillResults.right.protocolFeePaid = protocolFee;
 | 
			
		||||
 | 
			
		||||
            // Construct an array of makers and fee amounts so that the staking contract will only need to be called once.
 | 
			
		||||
            address[] memory makers = new address[](2);
 | 
			
		||||
            makers[0] = leftOrder.makerAddress;
 | 
			
		||||
            makers[1] = rightOrder.makerAddress;
 | 
			
		||||
            uint256[] memory fees = new uint256[](2);
 | 
			
		||||
            fees[0] = protocolFee;
 | 
			
		||||
            fees[1] = protocolFee;
 | 
			
		||||
            // Create a stack variable for the value that will be sent to the feeCollector when `payProtocolFee` is called.
 | 
			
		||||
            // This allows a gas optimization where the `leftOrder.makerAddress` only needs be loaded onto the stack once AND
 | 
			
		||||
            // a stack variable does not need to be allocated for the call.
 | 
			
		||||
            uint256 valuePaid = 0;
 | 
			
		||||
 | 
			
		||||
            // If sufficient ether was sent to the contract, the protocol fee should be paid in ETH.
 | 
			
		||||
            // Otherwise the fee should be paid in WETH.
 | 
			
		||||
            // Pay the left order's protocol fee.
 | 
			
		||||
            if (address(this).balance >= 2 * protocolFee) {
 | 
			
		||||
                // Forward the protocol fees
 | 
			
		||||
                IStaking(staking).batchPayProtocolFees.value(2 * protocolFee)(makers, fees);
 | 
			
		||||
            } else {
 | 
			
		||||
                // Transfer the weth from the takerAddress.
 | 
			
		||||
                // Note: `_dispatchTransferFrom` is only called once as a gas optimization.
 | 
			
		||||
                _dispatchTransferFrom(
 | 
			
		||||
                    leftOrderHash,
 | 
			
		||||
                    WETH_ASSET_DATA,
 | 
			
		||||
                    takerAddress,
 | 
			
		||||
                    staking,
 | 
			
		||||
                    2 * protocolFee
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                // Attribute the protocol fees to the maker addresses
 | 
			
		||||
                IStaking(staking).batchRecordProtocolFees(makers, fees);
 | 
			
		||||
                valuePaid = 2 * protocolFee;
 | 
			
		||||
            }
 | 
			
		||||
            IStaking(feeCollector).payProtocolFee.value(valuePaid)(leftOrder.makerAddress, takerAddress, protocolFee);
 | 
			
		||||
            IStaking(feeCollector).payProtocolFee.value(valuePaid)(rightOrder.makerAddress, takerAddress, protocolFee);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Settle taker fees.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,67 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/Ownable.sol";
 | 
			
		||||
import "./interfaces/IStakingManager.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract MixinStakingManager is
 | 
			
		||||
    IStakingManager,
 | 
			
		||||
    Ownable
 | 
			
		||||
{
 | 
			
		||||
    // The protocol fee multiplier -- the owner can update this field.
 | 
			
		||||
    uint256 public protocolFeeMultiplier;
 | 
			
		||||
 | 
			
		||||
    // The address of the registered staking contract -- the owner can update this field.
 | 
			
		||||
    address public staking;
 | 
			
		||||
 | 
			
		||||
    // The address of the wrapped ether contract -- the owner can update this field.
 | 
			
		||||
    address public weth;
 | 
			
		||||
 | 
			
		||||
    /// @dev Allows the owner to update the protocol fee multiplier.
 | 
			
		||||
    /// @param updatedProtocolFeeMultiplier The updated protocol fee multiplier.
 | 
			
		||||
    function updateProtocolFeeMultiplier(uint256 updatedProtocolFeeMultiplier)
 | 
			
		||||
        external
 | 
			
		||||
        onlyOwner()
 | 
			
		||||
    {
 | 
			
		||||
        emit UpdatedProtocolFeeMultiplier(protocolFeeMultiplier, updatedProtocolFeeMultiplier);
 | 
			
		||||
        protocolFeeMultiplier = updatedProtocolFeeMultiplier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Allows the owner to update the staking address.
 | 
			
		||||
    /// @param updatedStaking The updated staking contract address.
 | 
			
		||||
    function updateStakingAddress(address updatedStaking)
 | 
			
		||||
        external
 | 
			
		||||
        onlyOwner()
 | 
			
		||||
    {
 | 
			
		||||
        emit UpdatedStakingAddress(staking, updatedStaking);
 | 
			
		||||
        staking = updatedStaking;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Allows the owner to update the WETH address.
 | 
			
		||||
    /// @param updatedWeth The updated WETH contract address.
 | 
			
		||||
    function updateWethAddress(address updatedWeth)
 | 
			
		||||
        external
 | 
			
		||||
        onlyOwner()
 | 
			
		||||
    {
 | 
			
		||||
        emit UpdatedWethAddress(weth, updatedWeth);
 | 
			
		||||
        weth = updatedWeth;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -53,7 +53,7 @@ contract MixinTransactions is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refund
 | 
			
		||||
        disableRefundUntilEnd
 | 
			
		||||
        returns (bytes memory)
 | 
			
		||||
    {
 | 
			
		||||
        return _executeTransaction(transaction, signature);
 | 
			
		||||
@@ -69,7 +69,7 @@ contract MixinTransactions is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refund
 | 
			
		||||
        disableRefundUntilEnd
 | 
			
		||||
        returns (bytes[] memory)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 length = transactions.length;
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ contract MixinWrapperFunctions is
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        nonReentrant
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
        returns (LibFillResults.FillResults memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        fillResults = _fillOrKillOrder(
 | 
			
		||||
@@ -59,6 +59,10 @@ contract MixinWrapperFunctions is
 | 
			
		||||
        return fillResults;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Note: This function only needs `refundFinalBalance` modifier because ether will not
 | 
			
		||||
    //        be returned in the event that the delegatecall fails. This said, there is no
 | 
			
		||||
    //        reason to invoke `disableRefundUntilEnd` because it is cheaper to use this modifier
 | 
			
		||||
    //        and the inner refund will not affect the logic of this call.
 | 
			
		||||
    /// @dev Fills the input order.
 | 
			
		||||
    ///      Returns a null FillResults instance if the transaction would otherwise revert.
 | 
			
		||||
    /// @param order Order struct containing order specifications.
 | 
			
		||||
@@ -72,7 +76,7 @@ contract MixinWrapperFunctions is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refund
 | 
			
		||||
        refundFinalBalance
 | 
			
		||||
        returns (LibFillResults.FillResults memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        // ABI encode calldata for `fillOrder`
 | 
			
		||||
@@ -85,7 +89,7 @@ contract MixinWrapperFunctions is
 | 
			
		||||
 | 
			
		||||
        (bool didSucceed, bytes memory returnData) = address(this).delegatecall(fillOrderCalldata);
 | 
			
		||||
        if (didSucceed) {
 | 
			
		||||
            assert(returnData.length == 128);
 | 
			
		||||
            assert(returnData.length == 160);
 | 
			
		||||
            fillResults = abi.decode(returnData, (LibFillResults.FillResults));
 | 
			
		||||
        }
 | 
			
		||||
        // fillResults values will be 0 by default if call was unsuccessful
 | 
			
		||||
@@ -105,7 +109,7 @@ contract MixinWrapperFunctions is
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        nonReentrant
 | 
			
		||||
        refund
 | 
			
		||||
        disableRefundUntilEnd
 | 
			
		||||
        returns (LibFillResults.FillResults[] memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 ordersLength = orders.length;
 | 
			
		||||
@@ -133,7 +137,7 @@ contract MixinWrapperFunctions is
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        nonReentrant
 | 
			
		||||
        refund
 | 
			
		||||
        disableRefundUntilEnd
 | 
			
		||||
        returns (LibFillResults.FillResults[] memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 ordersLength = orders.length;
 | 
			
		||||
@@ -160,7 +164,7 @@ contract MixinWrapperFunctions is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refund
 | 
			
		||||
        // disableRefundUntilEnd
 | 
			
		||||
        returns (LibFillResults.FillResults[] memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 ordersLength = orders.length;
 | 
			
		||||
@@ -187,7 +191,7 @@ contract MixinWrapperFunctions is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refund
 | 
			
		||||
        disableRefundUntilEnd
 | 
			
		||||
        returns (LibFillResults.FillResults memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        bytes memory takerAssetData = orders[0].takerAssetData;
 | 
			
		||||
@@ -233,7 +237,7 @@ contract MixinWrapperFunctions is
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        refund
 | 
			
		||||
        disableRefundUntilEnd
 | 
			
		||||
        returns (LibFillResults.FillResults memory fillResults)
 | 
			
		||||
    {
 | 
			
		||||
        bytes memory makerAssetData = orders[0].makerAssetData;
 | 
			
		||||
@@ -333,22 +337,6 @@ contract MixinWrapperFunctions is
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches information for all passed in orders.
 | 
			
		||||
    /// @param orders Array of order specifications.
 | 
			
		||||
    /// @return Array of OrderInfo instances that correspond to each order.
 | 
			
		||||
    function getOrdersInfo(LibOrder.Order[] memory orders)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (LibOrder.OrderInfo[] memory)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 ordersLength = orders.length;
 | 
			
		||||
        LibOrder.OrderInfo[] memory ordersInfo = new LibOrder.OrderInfo[](ordersLength);
 | 
			
		||||
        for (uint256 i = 0; i != ordersLength; i++) {
 | 
			
		||||
            ordersInfo[i] = getOrderInfo(orders[i]);
 | 
			
		||||
        }
 | 
			
		||||
        return ordersInfo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
 | 
			
		||||
    /// @param order Order struct containing order specifications.
 | 
			
		||||
    /// @param takerAssetFillAmount Desired amount of takerAsset to sell.
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,9 @@ import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
 | 
			
		||||
 | 
			
		||||
contract IExchangeCore {
 | 
			
		||||
 | 
			
		||||
    // keccak256("Fill(address,address,bytes32,address,address,uint256,uint256,uint256,uint256,uint256,bool,bytes,bytes,bytes,bytes)")
 | 
			
		||||
    bytes32 internal constant FILL_EVENT_TOPIC = 0x266de417a663e51231ccdf89b2794cea06fde5e2c433d76473160b32d31fd867;
 | 
			
		||||
 | 
			
		||||
    // Fill event is emitted whenever an order is filled.
 | 
			
		||||
    event Fill(
 | 
			
		||||
        address indexed makerAddress,         // Address that created the order.
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,9 @@ pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
contract IProtocolFees {
 | 
			
		||||
 | 
			
		||||
    // The proxy id of the weth asset proxy.
 | 
			
		||||
    bytes internal constant WETH_ASSET_DATA = hex"f47261b0";
 | 
			
		||||
 | 
			
		||||
    // Logs updates to the protocol fee multiplier.
 | 
			
		||||
    event UpdatedProtocolFeeMultiplier(uint256 oldProtocolFeeMultiplier, uint256 updatedProtocolFeeMultiplier);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -154,12 +154,4 @@ contract IWrapperFunctions {
 | 
			
		||||
    /// @param orders Array of order specifications.
 | 
			
		||||
    function batchCancelOrders(LibOrder.Order[] memory orders)
 | 
			
		||||
        public;
 | 
			
		||||
 | 
			
		||||
    /// @dev Fetches information for all passed in orders
 | 
			
		||||
    /// @param orders Array of order specifications.
 | 
			
		||||
    /// @return Array of OrderInfo instances that correspond to each order.
 | 
			
		||||
    function getOrdersInfo(LibOrder.Order[] memory orders)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (LibOrder.OrderInfo[] memory);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -92,6 +92,7 @@ contract TestWrapperFunctions is
 | 
			
		||||
        fillResults.takerAssetFilledAmount = order.takerAssetAmount;
 | 
			
		||||
        fillResults.makerFeePaid = order.makerFee;
 | 
			
		||||
        fillResults.takerFeePaid = order.takerFee;
 | 
			
		||||
        fillResults.protocolFeePaid = protocolFeeMultiplier;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridden to only log arguments and revert with certain inputs.
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,6 @@ import * as MixinExchangeCore from '../generated-artifacts/MixinExchangeCore.jso
 | 
			
		||||
import * as MixinMatchOrders from '../generated-artifacts/MixinMatchOrders.json';
 | 
			
		||||
import * as MixinProtocolFees from '../generated-artifacts/MixinProtocolFees.json';
 | 
			
		||||
import * as MixinSignatureValidator from '../generated-artifacts/MixinSignatureValidator.json';
 | 
			
		||||
import * as MixinStakingManager from '../generated-artifacts/MixinStakingManager.json';
 | 
			
		||||
import * as MixinTransactions from '../generated-artifacts/MixinTransactions.json';
 | 
			
		||||
import * as MixinTransferSimulator from '../generated-artifacts/MixinTransferSimulator.json';
 | 
			
		||||
import * as MixinWrapperFunctions from '../generated-artifacts/MixinWrapperFunctions.json';
 | 
			
		||||
@@ -49,7 +48,6 @@ export const artifacts = {
 | 
			
		||||
    MixinMatchOrders: MixinMatchOrders as ContractArtifact,
 | 
			
		||||
    MixinProtocolFees: MixinProtocolFees as ContractArtifact,
 | 
			
		||||
    MixinSignatureValidator: MixinSignatureValidator as ContractArtifact,
 | 
			
		||||
    MixinStakingManager: MixinStakingManager as ContractArtifact,
 | 
			
		||||
    MixinTransactions: MixinTransactions as ContractArtifact,
 | 
			
		||||
    MixinTransferSimulator: MixinTransferSimulator as ContractArtifact,
 | 
			
		||||
    MixinWrapperFunctions: MixinWrapperFunctions as ContractArtifact,
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,6 @@ export * from '../generated-wrappers/mixin_exchange_core';
 | 
			
		||||
export * from '../generated-wrappers/mixin_match_orders';
 | 
			
		||||
export * from '../generated-wrappers/mixin_protocol_fees';
 | 
			
		||||
export * from '../generated-wrappers/mixin_signature_validator';
 | 
			
		||||
export * from '../generated-wrappers/mixin_staking_manager';
 | 
			
		||||
export * from '../generated-wrappers/mixin_transactions';
 | 
			
		||||
export * from '../generated-wrappers/mixin_transfer_simulator';
 | 
			
		||||
export * from '../generated-wrappers/mixin_wrapper_functions';
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ import {
 | 
			
		||||
    Web3ProviderEngine,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { orderHashUtils } from '@0x/order-utils';
 | 
			
		||||
import { AssetProxyId, FillResults, SignedOrder } from '@0x/types';
 | 
			
		||||
import { FillResults, SignedOrder } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
			
		||||
import { TransactionReceiptWithDecodedLogs, ZeroExProvider } from 'ethereum-types';
 | 
			
		||||
@@ -33,6 +33,8 @@ export class FillOrderWrapper {
 | 
			
		||||
    private readonly _blockchainBalanceStore: BlockchainBalanceStore;
 | 
			
		||||
    private readonly _web3Wrapper: Web3Wrapper;
 | 
			
		||||
 | 
			
		||||
    // FIXME - Punting on these tests for now since no staking contract will be registered. This
 | 
			
		||||
    //         should be revisited when the protocol fee testing has been unit tested well.
 | 
			
		||||
    /**
 | 
			
		||||
     * Simulates matching two orders by transferring amounts defined in
 | 
			
		||||
     * `transferAmounts` and returns the results.
 | 
			
		||||
@@ -47,23 +49,18 @@ export class FillOrderWrapper {
 | 
			
		||||
        takerAddress: string,
 | 
			
		||||
        opts: { takerAssetFillAmount?: BigNumber } = {},
 | 
			
		||||
        initBalanceStore: BalanceStore,
 | 
			
		||||
        stakingOpts: {
 | 
			
		||||
            gasPrice: BigNumber;
 | 
			
		||||
            messageValue: BigNumber;
 | 
			
		||||
            protocolFeeMultiplier: BigNumber;
 | 
			
		||||
            stakingAddress: string;
 | 
			
		||||
            wethAddress: string;
 | 
			
		||||
        },
 | 
			
		||||
        // stakingOpts: {
 | 
			
		||||
        //     gasPrice: BigNumber;
 | 
			
		||||
        //     messageValue: BigNumber;
 | 
			
		||||
        //     protocolFeeMultiplier: BigNumber;
 | 
			
		||||
        //     stakingAddress: string;
 | 
			
		||||
        //     wethAddress: string;
 | 
			
		||||
        // },
 | 
			
		||||
    ): [FillResults, FillEventArgs, BalanceStore] {
 | 
			
		||||
        const balanceStore = LocalBalanceStore.create(initBalanceStore);
 | 
			
		||||
        const takerAssetFillAmount =
 | 
			
		||||
            opts.takerAssetFillAmount !== undefined ? opts.takerAssetFillAmount : signedOrder.takerAssetAmount;
 | 
			
		||||
        const fillResults = LibReferenceFunctions.calculateFillResults(
 | 
			
		||||
            signedOrder,
 | 
			
		||||
            takerAssetFillAmount,
 | 
			
		||||
            stakingOpts.protocolFeeMultiplier,
 | 
			
		||||
            stakingOpts.gasPrice,
 | 
			
		||||
        );
 | 
			
		||||
        const fillResults = LibReferenceFunctions.calculateFillResults(signedOrder, takerAssetFillAmount);
 | 
			
		||||
        const fillEvent = FillOrderWrapper.simulateFillEvent(signedOrder, takerAddress, fillResults);
 | 
			
		||||
        // Taker -> Maker
 | 
			
		||||
        balanceStore.transferAsset(
 | 
			
		||||
@@ -93,18 +90,20 @@ export class FillOrderWrapper {
 | 
			
		||||
            fillResults.makerFeePaid,
 | 
			
		||||
            signedOrder.makerFeeAssetData,
 | 
			
		||||
        );
 | 
			
		||||
        if (stakingOpts.messageValue.isGreaterThanOrEqualTo(fillResults.protocolFeePaid)) {
 | 
			
		||||
            // Pay the protocol fee in ETH.
 | 
			
		||||
            balanceStore.transferAsset(takerAddress, stakingOpts.stakingAddress, fillResults.protocolFeePaid, '');
 | 
			
		||||
        } else {
 | 
			
		||||
            // Pay the protocol fee in WETH.
 | 
			
		||||
            balanceStore.transferAsset(
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                stakingOpts.stakingAddress,
 | 
			
		||||
                fillResults.protocolFeePaid,
 | 
			
		||||
                AssetProxyId.ERC20,
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        // FIXME - Punting on these tests for now since no staking contract will be registered. This
 | 
			
		||||
        //         should be revisited when the protocol fee testing has been unit tested well.
 | 
			
		||||
        // if (stakingOpts.messageValue.isGreaterThanOrEqualTo(fillResults.protocolFeePaid)) {
 | 
			
		||||
        //     // Pay the protocol fee in ETH.
 | 
			
		||||
        //     balanceStore.transferAsset(takerAddress, stakingOpts.stakingAddress, fillResults.protocolFeePaid, '');
 | 
			
		||||
        // } else {
 | 
			
		||||
        //     // Pay the protocol fee in WETH.
 | 
			
		||||
        //     balanceStore.transferAsset(
 | 
			
		||||
        //         takerAddress,
 | 
			
		||||
        //         stakingOpts.stakingAddress,
 | 
			
		||||
        //         fillResults.protocolFeePaid,
 | 
			
		||||
        //         AssetProxyId.ERC20,
 | 
			
		||||
        //     );
 | 
			
		||||
        // }
 | 
			
		||||
        return [fillResults, fillEvent, balanceStore];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -168,6 +167,8 @@ export class FillOrderWrapper {
 | 
			
		||||
        return this._blockchainBalanceStore;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // FIXME - Punting on these tests for now since no staking contract will be registered. This
 | 
			
		||||
    //         should be revisited when the protocol fee testing has been unit tested well.
 | 
			
		||||
    /**
 | 
			
		||||
     * Fills an order and asserts the effects. This includes
 | 
			
		||||
     * 1. The order info (via `getOrderInfo`)
 | 
			
		||||
 
 | 
			
		||||
@@ -589,11 +589,11 @@ blockchainTests.resets('Exchange core', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should cancel only orders with a orderEpoch less than existing orderEpoch', async () => {
 | 
			
		||||
            // Cancel all transactions with a orderEpoch less than 1
 | 
			
		||||
            // Cancel all transactions with a orderEpoch less than 2
 | 
			
		||||
            const orderEpoch = new BigNumber(1);
 | 
			
		||||
            await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress);
 | 
			
		||||
 | 
			
		||||
            // Create 3 orders with orderEpoch values: 0,1,2,3
 | 
			
		||||
            // Create 4 orders with orderEpoch values: 0,1,2,3
 | 
			
		||||
            // Since we cancelled with orderEpoch=1, orders with orderEpoch<=1 will not be processed
 | 
			
		||||
            erc20Balances = await erc20Wrapper.getBalancesAsync();
 | 
			
		||||
            const signedOrders = [
 | 
			
		||||
 
 | 
			
		||||
@@ -164,26 +164,22 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
            return _.assign({}, ORDER_DEFAULTS, details);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // FIXME - This test definitely needs to be updated
 | 
			
		||||
        async function testUpdateFilledStateAsync(
 | 
			
		||||
            order: OrderWithoutDomain,
 | 
			
		||||
            orderTakerAssetFilledAmount: BigNumber,
 | 
			
		||||
            takerAddress: string,
 | 
			
		||||
            takerAssetFillAmount: BigNumber,
 | 
			
		||||
            protocolFeeMultiplier: BigNumber,
 | 
			
		||||
            gasPrice: BigNumber,
 | 
			
		||||
            isProtocolFeePaidInEth: boolean,
 | 
			
		||||
            // protocolFeeMultiplier: BigNumber,
 | 
			
		||||
            // gasPrice: BigNumber,
 | 
			
		||||
            // isProtocolFeePaidInEth: boolean,
 | 
			
		||||
        ): Promise<void> {
 | 
			
		||||
            const orderHash = randomHash();
 | 
			
		||||
            const fillResults = LibReferenceFunctions.calculateFillResults(
 | 
			
		||||
                order,
 | 
			
		||||
                takerAssetFillAmount,
 | 
			
		||||
                protocolFeeMultiplier,
 | 
			
		||||
                gasPrice,
 | 
			
		||||
            );
 | 
			
		||||
            const fillResults = LibReferenceFunctions.calculateFillResults(order, takerAssetFillAmount);
 | 
			
		||||
            const expectedFilledState = orderTakerAssetFilledAmount.plus(takerAssetFillAmount);
 | 
			
		||||
            const opts = isProtocolFeePaidInEth
 | 
			
		||||
                ? { value: fillResults.protocolFeePaid }
 | 
			
		||||
                : { value: constants.ZERO_AMOUNT };
 | 
			
		||||
            // const opts = isProtocolFeePaidInEth
 | 
			
		||||
            //    ? { value: fillResults.protocolFeePaid }
 | 
			
		||||
            //    : { value: constants.ZERO_AMOUNT };
 | 
			
		||||
            // CAll `testUpdateFilledState()`, which will set the `filled`
 | 
			
		||||
            // state for this order to `orderTakerAssetFilledAmount` before
 | 
			
		||||
            // calling `_updateFilledState()`.
 | 
			
		||||
@@ -194,7 +190,7 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
                    orderHash,
 | 
			
		||||
                    orderTakerAssetFilledAmount,
 | 
			
		||||
                    fillResults,
 | 
			
		||||
                    opts,
 | 
			
		||||
                    // opts, // FIXME
 | 
			
		||||
                ),
 | 
			
		||||
            );
 | 
			
		||||
            // Grab the new `filled` state for this order.
 | 
			
		||||
@@ -214,8 +210,8 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
            expect(fillEvent.args.takerAssetFilledAmount).to.bignumber.eq(fillResults.takerAssetFilledAmount);
 | 
			
		||||
            expect(fillEvent.args.makerFeePaid).to.bignumber.eq(fillResults.makerFeePaid);
 | 
			
		||||
            expect(fillEvent.args.takerFeePaid).to.bignumber.eq(fillResults.takerFeePaid);
 | 
			
		||||
            expect(fillEvent.args.protocolFeePaid).to.bignumber.eq(fillResults.protocolFeePaid);
 | 
			
		||||
            expect(fillEvent.args.isProtocolFeePaidInEth).to.eq(isProtocolFeePaidInEth);
 | 
			
		||||
            // expect(fillEvent.args.protocolFeePaid).to.bignumber.eq(fillResults.protocolFeePaid);
 | 
			
		||||
            // expect(fillEvent.args.isProtocolFeePaidInEth).to.eq(isProtocolFeePaidInEth);
 | 
			
		||||
            expect(fillEvent.args.makerAssetData).to.eq(order.makerAssetData);
 | 
			
		||||
            expect(fillEvent.args.takerAssetData).to.eq(order.takerAssetData);
 | 
			
		||||
            expect(fillEvent.args.makerFeeAssetData).to.eq(order.makerFeeAssetData);
 | 
			
		||||
@@ -229,9 +225,6 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
                order.takerAssetAmount.times(0.1),
 | 
			
		||||
                randomAddress(),
 | 
			
		||||
                order.takerAssetAmount.times(0.25),
 | 
			
		||||
                new BigNumber(150000),
 | 
			
		||||
                new BigNumber(100000),
 | 
			
		||||
                true,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -242,9 +235,6 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
                order.takerAssetAmount.times(0.1),
 | 
			
		||||
                randomAddress(),
 | 
			
		||||
                order.takerAssetAmount.times(0.25),
 | 
			
		||||
                new BigNumber(100000),
 | 
			
		||||
                new BigNumber(150000),
 | 
			
		||||
                true,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -252,11 +242,13 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
            const order = makeOrder();
 | 
			
		||||
            const orderTakerAssetFilledAmount = constants.MAX_UINT256.dividedToIntegerBy(2);
 | 
			
		||||
            const takerAssetFillAmount = constants.MAX_UINT256.dividedToIntegerBy(2).plus(2);
 | 
			
		||||
            // FIXME
 | 
			
		||||
            const fillResults = {
 | 
			
		||||
                makerAssetFilledAmount: constants.ZERO_AMOUNT,
 | 
			
		||||
                takerAssetFilledAmount: takerAssetFillAmount,
 | 
			
		||||
                makerFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
                takerFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
                protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
            };
 | 
			
		||||
            const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                SafeMathRevertErrors.BinOpErrorCodes.AdditionOverflow,
 | 
			
		||||
@@ -297,11 +289,13 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
            const order = DEFAULT_ORDER;
 | 
			
		||||
            const orderHash = randomHash();
 | 
			
		||||
            const takerAddress = randomAddress();
 | 
			
		||||
            // FIXME
 | 
			
		||||
            const fillResults = {
 | 
			
		||||
                makerAssetFilledAmount: ONE_ETHER.times(2),
 | 
			
		||||
                takerAssetFilledAmount: ONE_ETHER.times(10),
 | 
			
		||||
                makerFeePaid: ONE_ETHER.times(0.01),
 | 
			
		||||
                takerFeePaid: ONE_ETHER.times(0.025),
 | 
			
		||||
                protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
            };
 | 
			
		||||
            const receipt = await logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
                await testExchange.settleOrder.sendTransactionAsync(orderHash, order, takerAddress, fillResults),
 | 
			
		||||
@@ -371,12 +365,14 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
                    takerAssetFilledAmount: ONE_ETHER.times(10),
 | 
			
		||||
                    makerFeePaid: ONE_ETHER.times(0.01),
 | 
			
		||||
                    takerFeePaid: constants.MAX_UINT256,
 | 
			
		||||
                    protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                },
 | 
			
		||||
                right: {
 | 
			
		||||
                    takerAssetFilledAmount: ONE_ETHER.times(20),
 | 
			
		||||
                    makerAssetFilledAmount: ONE_ETHER.times(4),
 | 
			
		||||
                    makerFeePaid: ONE_ETHER.times(0.02),
 | 
			
		||||
                    takerFeePaid: constants.MAX_UINT256_ROOT,
 | 
			
		||||
                    protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                },
 | 
			
		||||
                profitInLeftMakerAsset: ONE_ETHER,
 | 
			
		||||
                profitInRightMakerAsset: ONE_ETHER.times(2),
 | 
			
		||||
@@ -418,12 +414,14 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
                    takerAssetFilledAmount: ONE_ETHER.times(10),
 | 
			
		||||
                    makerFeePaid: ONE_ETHER.times(0.01),
 | 
			
		||||
                    takerFeePaid: constants.MAX_UINT256,
 | 
			
		||||
                    protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                },
 | 
			
		||||
                right: {
 | 
			
		||||
                    takerAssetFilledAmount: ONE_ETHER.times(20),
 | 
			
		||||
                    makerAssetFilledAmount: ONE_ETHER.times(4),
 | 
			
		||||
                    makerFeePaid: ONE_ETHER.times(0.02),
 | 
			
		||||
                    takerFeePaid: constants.MAX_UINT256_ROOT,
 | 
			
		||||
                    protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                },
 | 
			
		||||
                profitInLeftMakerAsset: ONE_ETHER,
 | 
			
		||||
                profitInRightMakerAsset: ONE_ETHER.times(2),
 | 
			
		||||
@@ -454,12 +452,14 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
                    takerAssetFilledAmount: ONE_ETHER.times(10),
 | 
			
		||||
                    makerFeePaid: ONE_ETHER.times(0.01),
 | 
			
		||||
                    takerFeePaid: ONE_ETHER.times(0.025),
 | 
			
		||||
                    protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                },
 | 
			
		||||
                right: {
 | 
			
		||||
                    takerAssetFilledAmount: ONE_ETHER.times(20),
 | 
			
		||||
                    makerAssetFilledAmount: ONE_ETHER.times(4),
 | 
			
		||||
                    makerFeePaid: ONE_ETHER.times(0.02),
 | 
			
		||||
                    takerFeePaid: ONE_ETHER.times(0.05),
 | 
			
		||||
                    protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                },
 | 
			
		||||
                profitInLeftMakerAsset: ONE_ETHER,
 | 
			
		||||
                profitInRightMakerAsset: ONE_ETHER.times(2),
 | 
			
		||||
@@ -550,12 +550,14 @@ blockchainTests('Exchange core internal functions', env => {
 | 
			
		||||
                    takerAssetFilledAmount: ONE_ETHER.times(10),
 | 
			
		||||
                    makerFeePaid: ONE_ETHER.times(0.01),
 | 
			
		||||
                    takerFeePaid: ONE_ETHER.times(0.025),
 | 
			
		||||
                    protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                },
 | 
			
		||||
                right: {
 | 
			
		||||
                    takerAssetFilledAmount: ONE_ETHER.times(20),
 | 
			
		||||
                    makerAssetFilledAmount: ONE_ETHER.times(4),
 | 
			
		||||
                    makerFeePaid: ONE_ETHER.times(0.02),
 | 
			
		||||
                    takerFeePaid: ONE_ETHER.times(0.05),
 | 
			
		||||
                    protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                },
 | 
			
		||||
                profitInLeftMakerAsset: ONE_ETHER,
 | 
			
		||||
                profitInRightMakerAsset: ONE_ETHER.times(2),
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,6 @@ import { OrderWithoutDomain as Order } from '@0x/types';
 | 
			
		||||
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { calculateFillResults } from '../src/reference_functions';
 | 
			
		||||
 | 
			
		||||
describe('Reference functions', () => {
 | 
			
		||||
    const ONE_ETHER = constants.ONE_ETHER;
 | 
			
		||||
    const EMPTY_ORDER: Order = {
 | 
			
		||||
@@ -44,7 +42,9 @@ describe('Reference functions', () => {
 | 
			
		||||
                takerAssetFilledAmount,
 | 
			
		||||
                order.makerAssetAmount,
 | 
			
		||||
            );
 | 
			
		||||
            return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
            return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(
 | 
			
		||||
                expectedError.message,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('reverts if computing `fillResults.makerFeePaid` overflows', () => {
 | 
			
		||||
@@ -65,7 +65,7 @@ describe('Reference functions', () => {
 | 
			
		||||
                makerAssetFilledAmount,
 | 
			
		||||
                order.makerFee,
 | 
			
		||||
            );
 | 
			
		||||
            return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
            return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('reverts if computing `fillResults.takerFeePaid` overflows', () => {
 | 
			
		||||
@@ -81,7 +81,7 @@ describe('Reference functions', () => {
 | 
			
		||||
                takerAssetFilledAmount,
 | 
			
		||||
                order.takerFee,
 | 
			
		||||
            );
 | 
			
		||||
            return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
            return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('reverts if `order.makerAssetAmount` is 0', () => {
 | 
			
		||||
@@ -91,7 +91,7 @@ describe('Reference functions', () => {
 | 
			
		||||
            });
 | 
			
		||||
            const takerAssetFilledAmount = ONE_ETHER;
 | 
			
		||||
            const expectedError = new LibMathRevertErrors.DivisionByZeroError();
 | 
			
		||||
            return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
            return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('reverts if `order.takerAssetAmount` is 0', () => {
 | 
			
		||||
@@ -101,7 +101,7 @@ describe('Reference functions', () => {
 | 
			
		||||
            });
 | 
			
		||||
            const takerAssetFilledAmount = ONE_ETHER;
 | 
			
		||||
            const expectedError = new LibMathRevertErrors.DivisionByZeroError();
 | 
			
		||||
            return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
            return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('reverts if there is a rounding error computing `makerAsssetFilledAmount`', () => {
 | 
			
		||||
@@ -115,7 +115,7 @@ describe('Reference functions', () => {
 | 
			
		||||
                order.takerAssetAmount,
 | 
			
		||||
                order.makerAssetAmount,
 | 
			
		||||
            );
 | 
			
		||||
            return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
            return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('reverts if there is a rounding error computing `makerFeePaid`', () => {
 | 
			
		||||
@@ -135,7 +135,7 @@ describe('Reference functions', () => {
 | 
			
		||||
                order.makerAssetAmount,
 | 
			
		||||
                order.makerFee,
 | 
			
		||||
            );
 | 
			
		||||
            return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
            return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('reverts if there is a rounding error computing `takerFeePaid`', () => {
 | 
			
		||||
@@ -155,7 +155,7 @@ describe('Reference functions', () => {
 | 
			
		||||
                order.makerAssetAmount,
 | 
			
		||||
                order.takerFee,
 | 
			
		||||
            );
 | 
			
		||||
            return expect(() => calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
            return expect(() => LibReferenceFunctions.calculateFillResults(order, takerAssetFilledAmount)).to.throw(expectedError.message);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,143 +0,0 @@
 | 
			
		||||
import { blockchainTests, constants, expect, LogDecoder } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BigNumber, OwnableRevertErrors } from '@0x/utils';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    artifacts,
 | 
			
		||||
    ExchangeContract,
 | 
			
		||||
    ExchangeUpdatedProtocolFeeMultiplierEventArgs,
 | 
			
		||||
    ExchangeUpdatedStakingAddressEventArgs,
 | 
			
		||||
    ExchangeUpdatedWethAddressEventArgs,
 | 
			
		||||
} from '../src';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('MixinStakingManager', env => {
 | 
			
		||||
    let accounts: string[];
 | 
			
		||||
    let exchange: ExchangeContract;
 | 
			
		||||
    let logDecoder: LogDecoder;
 | 
			
		||||
    let nonOwner: string;
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let staking: string;
 | 
			
		||||
    let weth: string;
 | 
			
		||||
 | 
			
		||||
    // The protocolFeeMultiplier that will be used to test the update functions.
 | 
			
		||||
    const protocolFeeMultiplier = new BigNumber(15000);
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        accounts = await env.web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        owner = accounts[0];
 | 
			
		||||
        nonOwner = accounts[1];
 | 
			
		||||
        staking = accounts[2];
 | 
			
		||||
        weth = accounts[3];
 | 
			
		||||
 | 
			
		||||
        // Update the from address of the txDefaults. This is the address that will become the owner.
 | 
			
		||||
        env.txDefaults.from = owner;
 | 
			
		||||
 | 
			
		||||
        // Deploy the exchange contract.
 | 
			
		||||
        exchange = await ExchangeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.Exchange,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            {},
 | 
			
		||||
            new BigNumber(1337),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Configure the log decoder
 | 
			
		||||
        logDecoder = new LogDecoder(env.web3Wrapper, artifacts);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    blockchainTests.resets('updateProtocolFeeMultiplier', () => {
 | 
			
		||||
        it('should revert if msg.sender != owner', async () => {
 | 
			
		||||
            const expectedError = new OwnableRevertErrors.OnlyOwnerError(nonOwner, owner);
 | 
			
		||||
 | 
			
		||||
            // Ensure that the transaction reverts with the expected rich error.
 | 
			
		||||
            const tx = exchange.updateStakingAddress.sendTransactionAsync(staking, {
 | 
			
		||||
                from: nonOwner,
 | 
			
		||||
            });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should succeed and emit an UpdatedProtocolFeeMultiplier event if msg.sender == owner', async () => {
 | 
			
		||||
            // Call the `updateProtocolFeeMultiplier()` function and get the receipt.
 | 
			
		||||
            const receipt = await logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
                await exchange.updateProtocolFeeMultiplier.sendTransactionAsync(protocolFeeMultiplier, {
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Verify that the staking address was actually updated to the correct address.
 | 
			
		||||
            const updated = await exchange.protocolFeeMultiplier.callAsync();
 | 
			
		||||
            expect(updated).bignumber.to.be.eq(protocolFeeMultiplier);
 | 
			
		||||
 | 
			
		||||
            // Ensure that the correct `UpdatedStakingAddress` event was logged.
 | 
			
		||||
            // tslint:disable:no-unnecessary-type-assertion
 | 
			
		||||
            const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<ExchangeUpdatedProtocolFeeMultiplierEventArgs>;
 | 
			
		||||
            expect(updatedEvent.event).to.be.eq('UpdatedProtocolFeeMultiplier');
 | 
			
		||||
            expect(updatedEvent.args.oldProtocolFeeMultiplier).bignumber.to.be.eq(constants.ZERO_AMOUNT);
 | 
			
		||||
            expect(updatedEvent.args.updatedProtocolFeeMultiplier).bignumber.to.be.eq(protocolFeeMultiplier);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    blockchainTests.resets('updateStakingAddress', () => {
 | 
			
		||||
        it('should revert if msg.sender != owner', async () => {
 | 
			
		||||
            const expectedError = new OwnableRevertErrors.OnlyOwnerError(nonOwner, owner);
 | 
			
		||||
 | 
			
		||||
            // Ensure that the transaction reverts with the expected rich error.
 | 
			
		||||
            const tx = exchange.updateStakingAddress.sendTransactionAsync(staking, {
 | 
			
		||||
                from: nonOwner,
 | 
			
		||||
            });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should succeed and emit an UpdatedStakingAddress event if msg.sender == owner', async () => {
 | 
			
		||||
            // Call the `updateStakingAddress()` function and get the receipt.
 | 
			
		||||
            const receipt = await logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
                await exchange.updateStakingAddress.sendTransactionAsync(staking, {
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Verify that the staking address was actually updated to the correct address.
 | 
			
		||||
            const updated = await exchange.staking.callAsync();
 | 
			
		||||
            expect(updated).to.be.eq(staking);
 | 
			
		||||
 | 
			
		||||
            // Ensure that the correct `UpdatedStakingAddress` event was logged.
 | 
			
		||||
            // tslint:disable:no-unnecessary-type-assertion
 | 
			
		||||
            const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<ExchangeUpdatedStakingAddressEventArgs>;
 | 
			
		||||
            expect(updatedEvent.event).to.be.eq('UpdatedStakingAddress');
 | 
			
		||||
            expect(updatedEvent.args.oldStaking).to.be.eq(constants.NULL_ADDRESS);
 | 
			
		||||
            expect(updatedEvent.args.updatedStaking).to.be.eq(staking);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    blockchainTests.resets('updateWethAddress', () => {
 | 
			
		||||
        it('should revert if msg.sender != owner', async () => {
 | 
			
		||||
            const expectedError = new OwnableRevertErrors.OnlyOwnerError(nonOwner, owner);
 | 
			
		||||
 | 
			
		||||
            // Ensure that the transaction reverts with the expected rich error.
 | 
			
		||||
            const tx = exchange.updateWethAddress.sendTransactionAsync(weth, {
 | 
			
		||||
                from: nonOwner,
 | 
			
		||||
            });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should succeed and emit an UpdatedStakingAddress event if msg.sender == owner', async () => {
 | 
			
		||||
            // Call the `updateWethAddress()` function and get the receipt.
 | 
			
		||||
            const receipt = await logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
                await exchange.updateWethAddress.sendTransactionAsync(weth, {
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                }),
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            // Verify that the staking address was actually updated to the correct address.
 | 
			
		||||
            const updated = await exchange.weth.callAsync();
 | 
			
		||||
            expect(updated).to.be.eq(weth);
 | 
			
		||||
 | 
			
		||||
            // Ensure that the correct `UpdatedStakingAddress` event was logged.
 | 
			
		||||
            // tslint:disable:no-unnecessary-type-assertion
 | 
			
		||||
            const updatedEvent = receipt.logs[0] as LogWithDecodedArgs<ExchangeUpdatedWethAddressEventArgs>;
 | 
			
		||||
            expect(updatedEvent.event).to.be.eq('UpdatedWethAddress');
 | 
			
		||||
            expect(updatedEvent.args.oldWeth).to.be.eq(constants.NULL_ADDRESS);
 | 
			
		||||
            expect(updatedEvent.args.updatedWeth).to.be.eq(weth);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1037,13 +1037,14 @@ blockchainTests.resets('Exchange transactions', env => {
 | 
			
		||||
                    const cancelTransaction = await makerTransactionFactory.newSignedTransactionAsync({
 | 
			
		||||
                        data: cancelData,
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    await exchangeWrapperContract.cancelOrdersUpTo.awaitTransactionSuccessAsync(
 | 
			
		||||
                        targetOrderEpoch,
 | 
			
		||||
                        cancelTransaction.salt,
 | 
			
		||||
                        cancelTransaction.expirationTimeSeconds,
 | 
			
		||||
                        cancelTransaction.signature,
 | 
			
		||||
                        // { from: makerAddress },
 | 
			
		||||
                        { from: makerAddress },
 | 
			
		||||
                        constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                    const takerAssetFillAmount = signedOrder.takerAssetAmount;
 | 
			
		||||
 
 | 
			
		||||
@@ -43,35 +43,35 @@ export class ExchangeWrapper {
 | 
			
		||||
    public async fillOrKillOrderAsync(
 | 
			
		||||
        signedOrder: SignedOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { takerAssetFillAmount?: BigNumber } = {},
 | 
			
		||||
        opts: { takerAssetFillAmount?: BigNumber; gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
 | 
			
		||||
        const txReceipt = await this._exchange.fillOrKillOrder.awaitTransactionSuccessAsync(
 | 
			
		||||
            params.order,
 | 
			
		||||
            params.takerAssetFillAmount,
 | 
			
		||||
            params.signature,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
        return txReceipt;
 | 
			
		||||
    }
 | 
			
		||||
    public async fillOrderNoThrowAsync(
 | 
			
		||||
        signedOrder: SignedOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { takerAssetFillAmount?: BigNumber; gas?: number } = {},
 | 
			
		||||
        opts: { takerAssetFillAmount?: BigNumber; gas?: number; gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
 | 
			
		||||
        const txReceipt = await this._exchange.fillOrderNoThrow.awaitTransactionSuccessAsync(
 | 
			
		||||
            params.order,
 | 
			
		||||
            params.takerAssetFillAmount,
 | 
			
		||||
            params.signature,
 | 
			
		||||
            { from, gas: opts.gas },
 | 
			
		||||
            { from, gas: opts.gas, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
        return txReceipt;
 | 
			
		||||
    }
 | 
			
		||||
    public async batchFillOrdersAsync(
 | 
			
		||||
        orders: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { takerAssetFillAmounts?: BigNumber[] } = {},
 | 
			
		||||
        opts: { takerAssetFillAmounts?: BigNumber[]; gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        return this._exchange.batchFillOrders.awaitTransactionSuccessAsync(
 | 
			
		||||
            orders,
 | 
			
		||||
@@ -79,13 +79,13 @@ export class ExchangeWrapper {
 | 
			
		||||
                ? orders.map(signedOrder => signedOrder.takerAssetAmount)
 | 
			
		||||
                : opts.takerAssetFillAmounts,
 | 
			
		||||
            orders.map(signedOrder => signedOrder.signature),
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async batchFillOrKillOrdersAsync(
 | 
			
		||||
        orders: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { takerAssetFillAmounts?: BigNumber[] } = {},
 | 
			
		||||
        opts: { takerAssetFillAmounts?: BigNumber[]; gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        return this._exchange.batchFillOrKillOrders.awaitTransactionSuccessAsync(
 | 
			
		||||
            orders,
 | 
			
		||||
@@ -93,13 +93,13 @@ export class ExchangeWrapper {
 | 
			
		||||
                ? orders.map(signedOrder => signedOrder.takerAssetAmount)
 | 
			
		||||
                : opts.takerAssetFillAmounts,
 | 
			
		||||
            orders.map(signedOrder => signedOrder.signature),
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async batchFillOrdersNoThrowAsync(
 | 
			
		||||
        orders: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { takerAssetFillAmounts?: BigNumber[]; gas?: number } = {},
 | 
			
		||||
        opts: { takerAssetFillAmounts?: BigNumber[]; gas?: number; gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        return this._exchange.batchFillOrdersNoThrow.awaitTransactionSuccessAsync(
 | 
			
		||||
            orders,
 | 
			
		||||
@@ -107,25 +107,25 @@ export class ExchangeWrapper {
 | 
			
		||||
                ? orders.map(signedOrder => signedOrder.takerAssetAmount)
 | 
			
		||||
                : opts.takerAssetFillAmounts,
 | 
			
		||||
            orders.map(signedOrder => signedOrder.signature),
 | 
			
		||||
            { from, gas: opts.gas },
 | 
			
		||||
            { from, gas: opts.gas, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async marketSellOrdersNoThrowAsync(
 | 
			
		||||
        orders: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { takerAssetFillAmount: BigNumber; gas?: number },
 | 
			
		||||
        opts: { takerAssetFillAmount: BigNumber; gas?: number; gasPrice?: BigNumber },
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        return this._exchange.marketSellOrdersNoThrow.awaitTransactionSuccessAsync(
 | 
			
		||||
            orders,
 | 
			
		||||
            opts.takerAssetFillAmount,
 | 
			
		||||
            orders.map(signedOrder => signedOrder.signature),
 | 
			
		||||
            { from, gas: opts.gas },
 | 
			
		||||
            { from, gas: opts.gas, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async marketBuyOrdersNoThrowAsync(
 | 
			
		||||
        orders: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { makerAssetFillAmount: BigNumber; gas?: number },
 | 
			
		||||
        opts: { makerAssetFillAmount: BigNumber; gas?: number; gasPrice?: BigNumber },
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        return this._exchange.marketBuyOrdersNoThrow.awaitTransactionSuccessAsync(
 | 
			
		||||
            orders,
 | 
			
		||||
@@ -180,22 +180,23 @@ export class ExchangeWrapper {
 | 
			
		||||
    public async executeTransactionAsync(
 | 
			
		||||
        signedTransaction: SignedZeroExTransaction,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        return this._exchange.executeTransaction.awaitTransactionSuccessAsync(
 | 
			
		||||
            signedTransaction,
 | 
			
		||||
            signedTransaction.signature,
 | 
			
		||||
            {
 | 
			
		||||
                from,
 | 
			
		||||
            },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async batchExecuteTransactionsAsync(
 | 
			
		||||
        signedTransactions: SignedZeroExTransaction[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const signatures = signedTransactions.map(signedTransaction => signedTransaction.signature);
 | 
			
		||||
        return this._exchange.batchExecuteTransactions.awaitTransactionSuccessAsync(signedTransactions, signatures, {
 | 
			
		||||
            from,
 | 
			
		||||
            gasPrice: opts.gasPrice,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
 | 
			
		||||
@@ -214,14 +215,11 @@ export class ExchangeWrapper {
 | 
			
		||||
        const orderInfo = await this._exchange.getOrderInfo.callAsync(signedOrder);
 | 
			
		||||
        return orderInfo;
 | 
			
		||||
    }
 | 
			
		||||
    public async getOrdersInfoAsync(signedOrders: SignedOrder[]): Promise<OrderInfo[]> {
 | 
			
		||||
        const ordersInfo = (await this._exchange.getOrdersInfo.callAsync(signedOrders)) as OrderInfo[];
 | 
			
		||||
        return ordersInfo;
 | 
			
		||||
    }
 | 
			
		||||
    public async batchMatchOrdersAsync(
 | 
			
		||||
        signedOrdersLeft: SignedOrder[],
 | 
			
		||||
        signedOrdersRight: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
 | 
			
		||||
        return this._exchange.batchMatchOrders.awaitTransactionSuccessAsync(
 | 
			
		||||
@@ -229,25 +227,27 @@ export class ExchangeWrapper {
 | 
			
		||||
            params.rightOrders,
 | 
			
		||||
            params.leftSignatures,
 | 
			
		||||
            params.rightSignatures,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async batchMatchOrdersRawAsync(
 | 
			
		||||
        params: BatchMatchOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        return this._exchange.batchMatchOrders.awaitTransactionSuccessAsync(
 | 
			
		||||
            params.leftOrders,
 | 
			
		||||
            params.rightOrders,
 | 
			
		||||
            params.leftSignatures,
 | 
			
		||||
            params.rightSignatures,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async getBatchMatchOrdersResultsAsync(
 | 
			
		||||
        signedOrdersLeft: SignedOrder[],
 | 
			
		||||
        signedOrdersRight: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<BatchMatchedFillResults> {
 | 
			
		||||
        const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
 | 
			
		||||
        const batchMatchedFillResults = await this._exchange.batchMatchOrders.callAsync(
 | 
			
		||||
@@ -255,7 +255,7 @@ export class ExchangeWrapper {
 | 
			
		||||
            params.rightOrders,
 | 
			
		||||
            params.leftSignatures,
 | 
			
		||||
            params.rightSignatures,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
        return batchMatchedFillResults;
 | 
			
		||||
    }
 | 
			
		||||
@@ -263,6 +263,7 @@ export class ExchangeWrapper {
 | 
			
		||||
        signedOrdersLeft: SignedOrder[],
 | 
			
		||||
        signedOrdersRight: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
 | 
			
		||||
        return this._exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
 | 
			
		||||
@@ -270,25 +271,27 @@ export class ExchangeWrapper {
 | 
			
		||||
            params.rightOrders,
 | 
			
		||||
            params.leftSignatures,
 | 
			
		||||
            params.rightSignatures,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async batchMatchOrdersWithMaximalFillRawAsync(
 | 
			
		||||
        params: BatchMatchOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        return this._exchange.batchMatchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
 | 
			
		||||
            params.leftOrders,
 | 
			
		||||
            params.rightOrders,
 | 
			
		||||
            params.leftSignatures,
 | 
			
		||||
            params.rightSignatures,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async getBatchMatchOrdersWithMaximalFillResultsAsync(
 | 
			
		||||
        signedOrdersLeft: SignedOrder[],
 | 
			
		||||
        signedOrdersRight: SignedOrder[],
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<BatchMatchedFillResults> {
 | 
			
		||||
        const params = orderUtils.createBatchMatchOrders(signedOrdersLeft, signedOrdersRight);
 | 
			
		||||
        const batchMatchedFillResults = await this._exchange.batchMatchOrdersWithMaximalFill.callAsync(
 | 
			
		||||
@@ -296,7 +299,7 @@ export class ExchangeWrapper {
 | 
			
		||||
            params.rightOrders,
 | 
			
		||||
            params.leftSignatures,
 | 
			
		||||
            params.rightSignatures,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
        return batchMatchedFillResults;
 | 
			
		||||
    }
 | 
			
		||||
@@ -304,6 +307,7 @@ export class ExchangeWrapper {
 | 
			
		||||
        signedOrderLeft: SignedOrder,
 | 
			
		||||
        signedOrderRight: SignedOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
 | 
			
		||||
        const txReceipt = await this._exchange.matchOrders.awaitTransactionSuccessAsync(
 | 
			
		||||
@@ -311,7 +315,7 @@ export class ExchangeWrapper {
 | 
			
		||||
            params.right,
 | 
			
		||||
            params.leftSignature,
 | 
			
		||||
            params.rightSignature,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
        return txReceipt;
 | 
			
		||||
    }
 | 
			
		||||
@@ -319,6 +323,7 @@ export class ExchangeWrapper {
 | 
			
		||||
        signedOrderLeft: SignedOrder,
 | 
			
		||||
        signedOrderRight: SignedOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<MatchedFillResults> {
 | 
			
		||||
        const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
 | 
			
		||||
        const matchedFillResults = await this._exchange.matchOrders.callAsync(
 | 
			
		||||
@@ -326,7 +331,7 @@ export class ExchangeWrapper {
 | 
			
		||||
            params.right,
 | 
			
		||||
            params.leftSignature,
 | 
			
		||||
            params.rightSignature,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
        return matchedFillResults;
 | 
			
		||||
    }
 | 
			
		||||
@@ -334,6 +339,7 @@ export class ExchangeWrapper {
 | 
			
		||||
        signedOrderLeft: SignedOrder,
 | 
			
		||||
        signedOrderRight: SignedOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
 | 
			
		||||
        return this._exchange.matchOrdersWithMaximalFill.awaitTransactionSuccessAsync(
 | 
			
		||||
@@ -341,13 +347,14 @@ export class ExchangeWrapper {
 | 
			
		||||
            params.right,
 | 
			
		||||
            params.leftSignature,
 | 
			
		||||
            params.rightSignature,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    public async getMatchOrdersWithMaximalFillResultsAsync(
 | 
			
		||||
        signedOrderLeft: SignedOrder,
 | 
			
		||||
        signedOrderRight: SignedOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { gasPrice?: BigNumber },
 | 
			
		||||
    ): Promise<MatchedFillResults> {
 | 
			
		||||
        const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight);
 | 
			
		||||
        const matchedFillResults = await this._exchange.matchOrdersWithMaximalFill.callAsync(
 | 
			
		||||
@@ -355,21 +362,21 @@ export class ExchangeWrapper {
 | 
			
		||||
            params.right,
 | 
			
		||||
            params.leftSignature,
 | 
			
		||||
            params.rightSignature,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
        return matchedFillResults;
 | 
			
		||||
    }
 | 
			
		||||
    public async getFillOrderResultsAsync(
 | 
			
		||||
        signedOrder: SignedOrder,
 | 
			
		||||
        from: string,
 | 
			
		||||
        opts: { takerAssetFillAmount?: BigNumber } = {},
 | 
			
		||||
        opts: { takerAssetFillAmount?: BigNumber; gasPrice?: BigNumber } = {},
 | 
			
		||||
    ): Promise<FillResults> {
 | 
			
		||||
        const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
 | 
			
		||||
        const fillResults = await this._exchange.fillOrder.callAsync(
 | 
			
		||||
            params.order,
 | 
			
		||||
            params.takerAssetFillAmount,
 | 
			
		||||
            params.signature,
 | 
			
		||||
            { from },
 | 
			
		||||
            { from, gasPrice: opts.gasPrice },
 | 
			
		||||
        );
 | 
			
		||||
        return fillResults;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ import {
 | 
			
		||||
    ERC721Wrapper,
 | 
			
		||||
    MultiAssetProxyContract,
 | 
			
		||||
} from '@0x/contracts-asset-proxy';
 | 
			
		||||
import { constants, expect, orderUtils, signingUtils } from '@0x/contracts-test-utils';
 | 
			
		||||
import { constants, expect, LogDecoder, orderUtils, signingUtils } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BalanceAndProxyAllowanceLazyStore, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
 | 
			
		||||
import { FillResults, Order, SignatureType, SignedOrder } from '@0x/types';
 | 
			
		||||
import { BigNumber, errorUtils, providerUtils, RevertError, StringRevertError } from '@0x/utils';
 | 
			
		||||
@@ -40,6 +40,7 @@ const EMPTY_FILL_RESULTS = {
 | 
			
		||||
    makerAssetFilledAmount: constants.ZERO_AMOUNT,
 | 
			
		||||
    makerFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
    takerFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
    protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum TestOutlook {
 | 
			
		||||
@@ -48,6 +49,7 @@ enum TestOutlook {
 | 
			
		||||
    Failure,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME - Really punting on this for now. It's possible that this won't need to be changed.
 | 
			
		||||
/**
 | 
			
		||||
 * Instantiates a new instance of FillOrderCombinatorialUtils. Since this method has some
 | 
			
		||||
 * required async setup, a factory method is required.
 | 
			
		||||
@@ -114,6 +116,8 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
 | 
			
		||||
        {},
 | 
			
		||||
        new BigNumber(chainId),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const logDecoder = new LogDecoder(web3Wrapper, artifacts);
 | 
			
		||||
    const exchangeWrapper = new ExchangeWrapper(exchangeContract, provider);
 | 
			
		||||
    await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, ownerAddress);
 | 
			
		||||
    await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, ownerAddress);
 | 
			
		||||
@@ -202,6 +206,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
 | 
			
		||||
        takerAddress,
 | 
			
		||||
        exchangeWrapper,
 | 
			
		||||
        assetWrapper,
 | 
			
		||||
        logDecoder,
 | 
			
		||||
    );
 | 
			
		||||
    return fillOrderCombinatorialUtils;
 | 
			
		||||
}
 | 
			
		||||
@@ -215,6 +220,7 @@ export class FillOrderCombinatorialUtils {
 | 
			
		||||
    public takerAddress: string;
 | 
			
		||||
    public exchangeWrapper: ExchangeWrapper;
 | 
			
		||||
    public assetWrapper: AssetWrapper;
 | 
			
		||||
    public logDecoder: LogDecoder;
 | 
			
		||||
    public balanceAndProxyAllowanceFetcher: SimpleAssetBalanceAndProxyAllowanceFetcher;
 | 
			
		||||
 | 
			
		||||
    public static generateFillOrderCombinations(): FillScenario[] {
 | 
			
		||||
@@ -445,6 +451,7 @@ export class FillOrderCombinatorialUtils {
 | 
			
		||||
        takerAddress: string,
 | 
			
		||||
        exchangeWrapper: ExchangeWrapper,
 | 
			
		||||
        assetWrapper: AssetWrapper,
 | 
			
		||||
        logDecoder: LogDecoder,
 | 
			
		||||
    ) {
 | 
			
		||||
        this.provider = provider;
 | 
			
		||||
        this.orderFactory = orderFactory;
 | 
			
		||||
@@ -454,6 +461,7 @@ export class FillOrderCombinatorialUtils {
 | 
			
		||||
        this.takerAddress = takerAddress;
 | 
			
		||||
        this.exchangeWrapper = exchangeWrapper;
 | 
			
		||||
        this.assetWrapper = assetWrapper;
 | 
			
		||||
        this.logDecoder = logDecoder;
 | 
			
		||||
        this.balanceAndProxyAllowanceFetcher = new SimpleAssetBalanceAndProxyAllowanceFetcher(assetWrapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -643,7 +651,7 @@ export class FillOrderCombinatorialUtils {
 | 
			
		||||
        );
 | 
			
		||||
        expect(exchangeLogs.length).to.be.equal(1, 'logs length');
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const log = txReceipt.logs[0] as LogWithDecodedArgs<ExchangeFillEventArgs>;
 | 
			
		||||
        const log = exchangeLogs[0] as LogWithDecodedArgs<ExchangeFillEventArgs>;
 | 
			
		||||
        expect(log.args.makerAddress, 'log.args.makerAddress').to.be.equal(makerAddress);
 | 
			
		||||
        expect(log.args.takerAddress, 'log.args.takerAddress').to.be.equal(this.takerAddress);
 | 
			
		||||
        expect(log.args.feeRecipientAddress, 'log.args.feeRecipientAddress').to.be.equal(feeRecipient);
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ export enum FillOrderError {
 | 
			
		||||
    TransferFailed = 'TRANSFER_FAILED',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME - Punting on protocol fees for now
 | 
			
		||||
/**
 | 
			
		||||
 * Simplified fill order simulator.
 | 
			
		||||
 */
 | 
			
		||||
@@ -121,6 +122,7 @@ export class FillOrderSimulator {
 | 
			
		||||
            makerAssetFilledAmount: makerAssetFillAmount,
 | 
			
		||||
            makerFeePaid,
 | 
			
		||||
            takerFeePaid,
 | 
			
		||||
            protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
 | 
			
		||||
import { ERC1155HoldingsByOwner, expect, OrderStatus } from '@0x/contracts-test-utils';
 | 
			
		||||
import { constants, ERC1155HoldingsByOwner, expect, OrderStatus } from '@0x/contracts-test-utils';
 | 
			
		||||
import { assetDataUtils, orderHashUtils } from '@0x/order-utils';
 | 
			
		||||
import { AssetProxyId, BatchMatchedFillResults, FillResults, MatchedFillResults, SignedOrder } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
@@ -235,6 +235,7 @@ export class MatchOrderTester {
 | 
			
		||||
        return expectedBatchMatchResults;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // FIXME - Punting on protocol fees until later
 | 
			
		||||
    /**
 | 
			
		||||
     * Matches two complementary orders and asserts results.
 | 
			
		||||
     * @param orders The matched orders and filled states.
 | 
			
		||||
@@ -266,6 +267,7 @@ export class MatchOrderTester {
 | 
			
		||||
                orders.leftOrder,
 | 
			
		||||
                orders.rightOrder,
 | 
			
		||||
                takerAddress,
 | 
			
		||||
                {}, // FIXME
 | 
			
		||||
            );
 | 
			
		||||
            transactionReceipt = await this._executeMatchOrdersWithMaximalFillAsync(
 | 
			
		||||
                orders.leftOrder,
 | 
			
		||||
@@ -1198,12 +1200,14 @@ function convertToMatchResults(result: MatchResults): MatchedFillResults {
 | 
			
		||||
            takerAssetFilledAmount: result.fills[0].takerAssetFilledAmount,
 | 
			
		||||
            makerFeePaid: result.fills[0].makerFeePaid,
 | 
			
		||||
            takerFeePaid: result.fills[0].takerFeePaid,
 | 
			
		||||
            protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
        },
 | 
			
		||||
        right: {
 | 
			
		||||
            makerAssetFilledAmount: result.fills[1].makerAssetFilledAmount,
 | 
			
		||||
            takerAssetFilledAmount: result.fills[1].takerAssetFilledAmount,
 | 
			
		||||
            makerFeePaid: result.fills[1].makerFeePaid,
 | 
			
		||||
            takerFeePaid: result.fills[1].takerFeePaid,
 | 
			
		||||
            protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
        },
 | 
			
		||||
        profitInLeftMakerAsset,
 | 
			
		||||
        profitInRightMakerAsset,
 | 
			
		||||
@@ -1222,6 +1226,7 @@ function convertToFillResults(result: FillEventArgs): FillResults {
 | 
			
		||||
        takerAssetFilledAmount: result.takerAssetFilledAmount,
 | 
			
		||||
        makerFeePaid: result.makerFeePaid,
 | 
			
		||||
        takerFeePaid: result.takerFeePaid,
 | 
			
		||||
        protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
    };
 | 
			
		||||
    return fillResults;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ import {
 | 
			
		||||
    ERC20BalancesByOwner,
 | 
			
		||||
    expect,
 | 
			
		||||
    getLatestBlockTimestampAsync,
 | 
			
		||||
    increaseTimeAndMineBlockAsync,
 | 
			
		||||
    OrderFactory,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { assetDataUtils, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
 | 
			
		||||
@@ -48,11 +47,15 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
    let defaultTakerAssetAddress: string;
 | 
			
		||||
    let defaultFeeAssetAddress: string;
 | 
			
		||||
 | 
			
		||||
    const DEFAULT_GAS_PRICE = new BigNumber(2);
 | 
			
		||||
    const PROTOCOL_FEE_MULTIPLIER = new BigNumber(150);
 | 
			
		||||
 | 
			
		||||
    const nullFillResults: FillResults = {
 | 
			
		||||
        makerAssetFilledAmount: constants.ZERO_AMOUNT,
 | 
			
		||||
        takerAssetFilledAmount: constants.ZERO_AMOUNT,
 | 
			
		||||
        makerFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
        takerFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
        protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
@@ -81,10 +84,16 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
        exchange = await ExchangeContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.Exchange,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            { ...env.txDefaults, from: owner },
 | 
			
		||||
            {},
 | 
			
		||||
            new BigNumber(chainId),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Set the protocol fee multiplier of the exchange
 | 
			
		||||
        await exchange.updateProtocolFeeMultiplier.awaitTransactionSuccessAsync(PROTOCOL_FEE_MULTIPLIER, {
 | 
			
		||||
            from: owner,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        exchangeWrapper = new ExchangeWrapper(exchange, env.provider);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
 | 
			
		||||
        await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
 | 
			
		||||
@@ -492,11 +501,14 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                        .dividedToIntegerBy(signedOrder.makerAssetAmount);
 | 
			
		||||
 | 
			
		||||
                    takerAssetFillAmounts.push(takerAssetFillAmount);
 | 
			
		||||
                    // FIXME - Punting on these tests for now since no staking contract will be registered. This
 | 
			
		||||
                    //         should be revisited when the protocol fee testing has been unit tested well.
 | 
			
		||||
                    expectedFillResults.push({
 | 
			
		||||
                        takerAssetFilledAmount: takerAssetFillAmount,
 | 
			
		||||
                        makerAssetFilledAmount,
 | 
			
		||||
                        makerFeePaid: makerFee,
 | 
			
		||||
                        takerFeePaid: takerFee,
 | 
			
		||||
                        protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    erc20Balances[makerAddress][makerAssetAddress] = erc20Balances[makerAddress][
 | 
			
		||||
@@ -522,11 +534,13 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                    ].plus(makerFee.plus(takerFee));
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // FIXME - Punting on these tests for now since no staking contract will be registered. This
 | 
			
		||||
                //         should be revisited when the protocol fee testing has been unit tested well.
 | 
			
		||||
                const fillResults = await exchange.batchFillOrders.callAsync(
 | 
			
		||||
                    signedOrders,
 | 
			
		||||
                    takerAssetFillAmounts,
 | 
			
		||||
                    signedOrders.map(signedOrder => signedOrder.signature),
 | 
			
		||||
                    { from: takerAddress },
 | 
			
		||||
                    { from: takerAddress, gasPrice: DEFAULT_GAS_PRICE },
 | 
			
		||||
                );
 | 
			
		||||
                await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, {
 | 
			
		||||
                    takerAssetFillAmounts,
 | 
			
		||||
@@ -559,11 +573,14 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                        .dividedToIntegerBy(signedOrder.makerAssetAmount);
 | 
			
		||||
 | 
			
		||||
                    takerAssetFillAmounts.push(takerAssetFillAmount);
 | 
			
		||||
                    // FIXME - Punting on these tests for now since no staking contract will be registered. This
 | 
			
		||||
                    //         should be revisited when the protocol fee testing has been unit tested well.
 | 
			
		||||
                    expectedFillResults.push({
 | 
			
		||||
                        takerAssetFilledAmount: takerAssetFillAmount,
 | 
			
		||||
                        makerAssetFilledAmount,
 | 
			
		||||
                        makerFeePaid: makerFee,
 | 
			
		||||
                        takerFeePaid: takerFee,
 | 
			
		||||
                        protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    erc20Balances[makerAddress][makerAssetAddress] = erc20Balances[makerAddress][
 | 
			
		||||
@@ -642,11 +659,14 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                        .dividedToIntegerBy(signedOrder.makerAssetAmount);
 | 
			
		||||
 | 
			
		||||
                    takerAssetFillAmounts.push(takerAssetFillAmount);
 | 
			
		||||
                    // FIXME - Punting on these tests for now since no staking contract will be registered. This
 | 
			
		||||
                    //         should be revisited when the protocol fee testing has been unit tested well.
 | 
			
		||||
                    expectedFillResults.push({
 | 
			
		||||
                        takerAssetFilledAmount: takerAssetFillAmount,
 | 
			
		||||
                        makerAssetFilledAmount,
 | 
			
		||||
                        makerFeePaid: makerFee,
 | 
			
		||||
                        takerFeePaid: takerFee,
 | 
			
		||||
                        protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    erc20Balances[makerAddress][makerAssetAddress] = erc20Balances[makerAddress][
 | 
			
		||||
@@ -712,11 +732,14 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                        .dividedToIntegerBy(signedOrder.makerAssetAmount);
 | 
			
		||||
 | 
			
		||||
                    takerAssetFillAmounts.push(takerAssetFillAmount);
 | 
			
		||||
                    // FIXME - Punting on these tests for now since no staking contract will be registered. This
 | 
			
		||||
                    //         should be revisited when the protocol fee testing has been unit tested well.
 | 
			
		||||
                    expectedFillResults.push({
 | 
			
		||||
                        takerAssetFilledAmount: takerAssetFillAmount,
 | 
			
		||||
                        makerAssetFilledAmount,
 | 
			
		||||
                        makerFeePaid: makerFee,
 | 
			
		||||
                        takerFeePaid: takerFee,
 | 
			
		||||
                        protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    erc20Balances[makerAddress][makerAssetAddress] = erc20Balances[makerAddress][
 | 
			
		||||
@@ -853,6 +876,7 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                        takerAssetFilledAmount: signedOrder.takerAssetAmount,
 | 
			
		||||
                        makerFeePaid: signedOrder.makerFee,
 | 
			
		||||
                        takerFeePaid: signedOrder.takerFee,
 | 
			
		||||
                        protocolFeePaid: constants.ZERO_AMOUNT, // FIXME - This is what is being used now.
 | 
			
		||||
                    }))
 | 
			
		||||
                    .reduce(
 | 
			
		||||
                        (totalFillResults, currentFillResults) => ({
 | 
			
		||||
@@ -864,6 +888,7 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                            ),
 | 
			
		||||
                            makerFeePaid: totalFillResults.makerFeePaid.plus(currentFillResults.makerFeePaid),
 | 
			
		||||
                            takerFeePaid: totalFillResults.takerFeePaid.plus(currentFillResults.takerFeePaid),
 | 
			
		||||
                            protocolFeePaid: totalFillResults.protocolFeePaid.plus(currentFillResults.protocolFeePaid),
 | 
			
		||||
                        }),
 | 
			
		||||
                        nullFillResults,
 | 
			
		||||
                    );
 | 
			
		||||
@@ -923,6 +948,7 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                        takerAssetFilledAmount: signedOrder.takerAssetAmount,
 | 
			
		||||
                        makerFeePaid: signedOrder.makerFee,
 | 
			
		||||
                        takerFeePaid: signedOrder.takerFee,
 | 
			
		||||
                        protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                    }))
 | 
			
		||||
                    .reduce(
 | 
			
		||||
                        (totalFillResults, currentFillResults) => ({
 | 
			
		||||
@@ -934,6 +960,7 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                            ),
 | 
			
		||||
                            makerFeePaid: totalFillResults.makerFeePaid.plus(currentFillResults.makerFeePaid),
 | 
			
		||||
                            takerFeePaid: totalFillResults.takerFeePaid.plus(currentFillResults.takerFeePaid),
 | 
			
		||||
                            protocolFeePaid: totalFillResults.protocolFeePaid.plus(currentFillResults.protocolFeePaid),
 | 
			
		||||
                        }),
 | 
			
		||||
                        nullFillResults,
 | 
			
		||||
                    );
 | 
			
		||||
@@ -1037,6 +1064,7 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                        takerAssetFilledAmount: signedOrder.takerAssetAmount,
 | 
			
		||||
                        makerFeePaid: signedOrder.makerFee,
 | 
			
		||||
                        takerFeePaid: signedOrder.takerFee,
 | 
			
		||||
                        protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                    }))
 | 
			
		||||
                    .reduce(
 | 
			
		||||
                        (totalFillResults, currentFillResults) => ({
 | 
			
		||||
@@ -1048,6 +1076,7 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                            ),
 | 
			
		||||
                            makerFeePaid: totalFillResults.makerFeePaid.plus(currentFillResults.makerFeePaid),
 | 
			
		||||
                            takerFeePaid: totalFillResults.takerFeePaid.plus(currentFillResults.takerFeePaid),
 | 
			
		||||
                            protocolFeePaid: totalFillResults.protocolFeePaid.plus(currentFillResults.protocolFeePaid),
 | 
			
		||||
                        }),
 | 
			
		||||
                        nullFillResults,
 | 
			
		||||
                    );
 | 
			
		||||
@@ -1108,6 +1137,7 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                        takerAssetFilledAmount: signedOrder.takerAssetAmount,
 | 
			
		||||
                        makerFeePaid: signedOrder.makerFee,
 | 
			
		||||
                        takerFeePaid: signedOrder.takerFee,
 | 
			
		||||
                        protocolFeePaid: constants.ZERO_AMOUNT, // FIXME
 | 
			
		||||
                    }))
 | 
			
		||||
                    .reduce(
 | 
			
		||||
                        (totalFillResults, currentFillResults) => ({
 | 
			
		||||
@@ -1119,6 +1149,7 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                            ),
 | 
			
		||||
                            makerFeePaid: totalFillResults.makerFeePaid.plus(currentFillResults.makerFeePaid),
 | 
			
		||||
                            takerFeePaid: totalFillResults.takerFeePaid.plus(currentFillResults.takerFeePaid),
 | 
			
		||||
                            protocolFeePaid: totalFillResults.protocolFeePaid.plus(currentFillResults.protocolFeePaid),
 | 
			
		||||
                        }),
 | 
			
		||||
                        nullFillResults,
 | 
			
		||||
                    );
 | 
			
		||||
@@ -1151,189 +1182,5 @@ blockchainTests.resets('Exchange wrappers', env => {
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('getOrdersInfo', () => {
 | 
			
		||||
            beforeEach(async () => {
 | 
			
		||||
                signedOrders = [
 | 
			
		||||
                    await orderFactory.newSignedOrderAsync(),
 | 
			
		||||
                    await orderFactory.newSignedOrderAsync(),
 | 
			
		||||
                    await orderFactory.newSignedOrderAsync(),
 | 
			
		||||
                ];
 | 
			
		||||
            });
 | 
			
		||||
            it('should get the correct information for multiple unfilled orders', async () => {
 | 
			
		||||
                const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
 | 
			
		||||
                expect(ordersInfo.length).to.be.equal(3);
 | 
			
		||||
                _.forEach(signedOrders, (signedOrder, index) => {
 | 
			
		||||
                    const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
                    const expectedTakerAssetFilledAmount = new BigNumber(0);
 | 
			
		||||
                    const expectedOrderStatus = OrderStatus.Fillable;
 | 
			
		||||
                    const orderInfo = ordersInfo[index];
 | 
			
		||||
                    expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
                    expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
 | 
			
		||||
                    expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it('should get the correct information for multiple partially filled orders', async () => {
 | 
			
		||||
                const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2));
 | 
			
		||||
                await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts });
 | 
			
		||||
                const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
 | 
			
		||||
                expect(ordersInfo.length).to.be.equal(3);
 | 
			
		||||
                _.forEach(signedOrders, (signedOrder, index) => {
 | 
			
		||||
                    const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
                    const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2);
 | 
			
		||||
                    const expectedOrderStatus = OrderStatus.Fillable;
 | 
			
		||||
                    const orderInfo = ordersInfo[index];
 | 
			
		||||
                    expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
                    expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
 | 
			
		||||
                    expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it('should get the correct information for multiple fully filled orders', async () => {
 | 
			
		||||
                await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress);
 | 
			
		||||
                const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
 | 
			
		||||
                expect(ordersInfo.length).to.be.equal(3);
 | 
			
		||||
                _.forEach(signedOrders, (signedOrder, index) => {
 | 
			
		||||
                    const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
                    const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount;
 | 
			
		||||
                    const expectedOrderStatus = OrderStatus.FullyFilled;
 | 
			
		||||
                    const orderInfo = ordersInfo[index];
 | 
			
		||||
                    expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
                    expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
 | 
			
		||||
                    expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it('should get the correct information for multiple cancelled and unfilled orders', async () => {
 | 
			
		||||
                await exchangeWrapper.batchCancelOrdersAsync(signedOrders, makerAddress);
 | 
			
		||||
                const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
 | 
			
		||||
                expect(ordersInfo.length).to.be.equal(3);
 | 
			
		||||
                _.forEach(signedOrders, (signedOrder, index) => {
 | 
			
		||||
                    const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
                    const expectedTakerAssetFilledAmount = new BigNumber(0);
 | 
			
		||||
                    const expectedOrderStatus = OrderStatus.Cancelled;
 | 
			
		||||
                    const orderInfo = ordersInfo[index];
 | 
			
		||||
                    expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
                    expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
 | 
			
		||||
                    expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it('should get the correct information for multiple cancelled and partially filled orders', async () => {
 | 
			
		||||
                const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2));
 | 
			
		||||
                await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts });
 | 
			
		||||
                await exchangeWrapper.batchCancelOrdersAsync(signedOrders, makerAddress);
 | 
			
		||||
                const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
 | 
			
		||||
                expect(ordersInfo.length).to.be.equal(3);
 | 
			
		||||
                _.forEach(signedOrders, (signedOrder, index) => {
 | 
			
		||||
                    const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
                    const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2);
 | 
			
		||||
                    const expectedOrderStatus = OrderStatus.Cancelled;
 | 
			
		||||
                    const orderInfo = ordersInfo[index];
 | 
			
		||||
                    expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
                    expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
 | 
			
		||||
                    expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it('should get the correct information for multiple expired and unfilled orders', async () => {
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const timeUntilExpiration = signedOrders[0].expirationTimeSeconds.minus(currentTimestamp).toNumber();
 | 
			
		||||
                await increaseTimeAndMineBlockAsync(timeUntilExpiration);
 | 
			
		||||
                const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
 | 
			
		||||
                expect(ordersInfo.length).to.be.equal(3);
 | 
			
		||||
                _.forEach(signedOrders, (signedOrder, index) => {
 | 
			
		||||
                    const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
                    const expectedTakerAssetFilledAmount = new BigNumber(0);
 | 
			
		||||
                    const expectedOrderStatus = OrderStatus.Expired;
 | 
			
		||||
                    const orderInfo = ordersInfo[index];
 | 
			
		||||
                    expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
                    expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
 | 
			
		||||
                    expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it('should get the correct information for multiple expired and partially filled orders', async () => {
 | 
			
		||||
                const takerAssetFillAmounts = _.map(signedOrders, signedOrder => signedOrder.takerAssetAmount.div(2));
 | 
			
		||||
                await exchangeWrapper.batchFillOrdersAsync(signedOrders, takerAddress, { takerAssetFillAmounts });
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const timeUntilExpiration = signedOrders[0].expirationTimeSeconds.minus(currentTimestamp).toNumber();
 | 
			
		||||
                await increaseTimeAndMineBlockAsync(timeUntilExpiration);
 | 
			
		||||
                const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
 | 
			
		||||
                expect(ordersInfo.length).to.be.equal(3);
 | 
			
		||||
                _.forEach(signedOrders, (signedOrder, index) => {
 | 
			
		||||
                    const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder);
 | 
			
		||||
                    const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount.div(2);
 | 
			
		||||
                    const expectedOrderStatus = OrderStatus.Expired;
 | 
			
		||||
                    const orderInfo = ordersInfo[index];
 | 
			
		||||
                    expect(orderInfo.orderHash).to.be.equal(expectedOrderHash);
 | 
			
		||||
                    expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount);
 | 
			
		||||
                    expect(orderInfo.orderStatus).to.equal(expectedOrderStatus);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            it('should get the correct information for a mix of unfilled, partially filled, fully filled, cancelled, and expired orders', async () => {
 | 
			
		||||
                const unfilledOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
                const partiallyFilledOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
                await exchangeWrapper.fillOrderAsync(partiallyFilledOrder, takerAddress, {
 | 
			
		||||
                    takerAssetFillAmount: partiallyFilledOrder.takerAssetAmount.div(2),
 | 
			
		||||
                });
 | 
			
		||||
                const fullyFilledOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
                await exchangeWrapper.fillOrderAsync(fullyFilledOrder, takerAddress);
 | 
			
		||||
                const cancelledOrder = await orderFactory.newSignedOrderAsync();
 | 
			
		||||
                await exchangeWrapper.cancelOrderAsync(cancelledOrder, makerAddress);
 | 
			
		||||
                const currentTimestamp = await getLatestBlockTimestampAsync();
 | 
			
		||||
                const expiredOrder = await orderFactory.newSignedOrderAsync({
 | 
			
		||||
                    expirationTimeSeconds: new BigNumber(currentTimestamp),
 | 
			
		||||
                });
 | 
			
		||||
                signedOrders = [unfilledOrder, partiallyFilledOrder, fullyFilledOrder, cancelledOrder, expiredOrder];
 | 
			
		||||
                const ordersInfo = await exchangeWrapper.getOrdersInfoAsync(signedOrders);
 | 
			
		||||
                expect(ordersInfo.length).to.be.equal(5);
 | 
			
		||||
 | 
			
		||||
                const expectedUnfilledOrderHash = orderHashUtils.getOrderHashHex(unfilledOrder);
 | 
			
		||||
                const expectedUnfilledTakerAssetFilledAmount = new BigNumber(0);
 | 
			
		||||
                const expectedUnfilledOrderStatus = OrderStatus.Fillable;
 | 
			
		||||
                const unfilledOrderInfo = ordersInfo[0];
 | 
			
		||||
                expect(unfilledOrderInfo.orderHash).to.be.equal(expectedUnfilledOrderHash);
 | 
			
		||||
                expect(unfilledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
 | 
			
		||||
                    expectedUnfilledTakerAssetFilledAmount,
 | 
			
		||||
                );
 | 
			
		||||
                expect(unfilledOrderInfo.orderStatus).to.be.equal(expectedUnfilledOrderStatus);
 | 
			
		||||
 | 
			
		||||
                const expectedPartialOrderHash = orderHashUtils.getOrderHashHex(partiallyFilledOrder);
 | 
			
		||||
                const expectedPartialTakerAssetFilledAmount = partiallyFilledOrder.takerAssetAmount.div(2);
 | 
			
		||||
                const expectedPartialOrderStatus = OrderStatus.Fillable;
 | 
			
		||||
                const partialOrderInfo = ordersInfo[1];
 | 
			
		||||
                expect(partialOrderInfo.orderHash).to.be.equal(expectedPartialOrderHash);
 | 
			
		||||
                expect(partialOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
 | 
			
		||||
                    expectedPartialTakerAssetFilledAmount,
 | 
			
		||||
                );
 | 
			
		||||
                expect(partialOrderInfo.orderStatus).to.be.equal(expectedPartialOrderStatus);
 | 
			
		||||
 | 
			
		||||
                const expectedFilledOrderHash = orderHashUtils.getOrderHashHex(fullyFilledOrder);
 | 
			
		||||
                const expectedFilledTakerAssetFilledAmount = fullyFilledOrder.takerAssetAmount;
 | 
			
		||||
                const expectedFilledOrderStatus = OrderStatus.FullyFilled;
 | 
			
		||||
                const filledOrderInfo = ordersInfo[2];
 | 
			
		||||
                expect(filledOrderInfo.orderHash).to.be.equal(expectedFilledOrderHash);
 | 
			
		||||
                expect(filledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
 | 
			
		||||
                    expectedFilledTakerAssetFilledAmount,
 | 
			
		||||
                );
 | 
			
		||||
                expect(filledOrderInfo.orderStatus).to.be.equal(expectedFilledOrderStatus);
 | 
			
		||||
 | 
			
		||||
                const expectedCancelledOrderHash = orderHashUtils.getOrderHashHex(cancelledOrder);
 | 
			
		||||
                const expectedCancelledTakerAssetFilledAmount = new BigNumber(0);
 | 
			
		||||
                const expectedCancelledOrderStatus = OrderStatus.Cancelled;
 | 
			
		||||
                const cancelledOrderInfo = ordersInfo[3];
 | 
			
		||||
                expect(cancelledOrderInfo.orderHash).to.be.equal(expectedCancelledOrderHash);
 | 
			
		||||
                expect(cancelledOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
 | 
			
		||||
                    expectedCancelledTakerAssetFilledAmount,
 | 
			
		||||
                );
 | 
			
		||||
                expect(cancelledOrderInfo.orderStatus).to.be.equal(expectedCancelledOrderStatus);
 | 
			
		||||
 | 
			
		||||
                const expectedExpiredOrderHash = orderHashUtils.getOrderHashHex(expiredOrder);
 | 
			
		||||
                const expectedExpiredTakerAssetFilledAmount = new BigNumber(0);
 | 
			
		||||
                const expectedExpiredOrderStatus = OrderStatus.Expired;
 | 
			
		||||
                const expiredOrderInfo = ordersInfo[4];
 | 
			
		||||
                expect(expiredOrderInfo.orderHash).to.be.equal(expectedExpiredOrderHash);
 | 
			
		||||
                expect(expiredOrderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(
 | 
			
		||||
                    expectedExpiredTakerAssetFilledAmount,
 | 
			
		||||
                );
 | 
			
		||||
                expect(expiredOrderInfo.orderStatus).to.be.equal(expectedExpiredOrderStatus);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
}); // tslint:disable-line:max-file-line-count
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@ blockchainTests('Exchange wrapper functions unit tests.', env => {
 | 
			
		||||
    const { ONE_ETHER, MAX_UINT256 } = constants;
 | 
			
		||||
    const { addFillResults, getPartialAmountFloor } = LibReferenceFunctions;
 | 
			
		||||
    const { safeSub } = UtilReferenceFunctions;
 | 
			
		||||
    const protocolFeeMultiplier = new BigNumber(150000);
 | 
			
		||||
    const randomAddress = () => hexRandom(constants.ADDRESS_LENGTH);
 | 
			
		||||
    const randomAssetData = () => hexRandom(34);
 | 
			
		||||
    const randomAmount = (maxAmount: BigNumber = ONE_ETHER) => maxAmount.times(_.random(0, 100, true).toFixed(12));
 | 
			
		||||
@@ -40,20 +41,30 @@ blockchainTests('Exchange wrapper functions unit tests.', env => {
 | 
			
		||||
        takerAssetFilledAmount: constants.ZERO_AMOUNT,
 | 
			
		||||
        makerFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
        takerFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
        protocolFeePaid: constants.ZERO_AMOUNT,
 | 
			
		||||
    };
 | 
			
		||||
    let testContract: TestWrapperFunctionsContract;
 | 
			
		||||
    let txHelper: TransactionHelper;
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let senderAddress: string;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        [senderAddress] = await env.getAccountAddressesAsync();
 | 
			
		||||
        [owner, senderAddress] = await env.getAccountAddressesAsync();
 | 
			
		||||
        txHelper = new TransactionHelper(env.web3Wrapper, artifacts);
 | 
			
		||||
        testContract = await TestWrapperFunctionsContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestWrapperFunctions,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            {
 | 
			
		||||
                ...env.txDefaults,
 | 
			
		||||
                from: owner,
 | 
			
		||||
            },
 | 
			
		||||
            {},
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Set the protocol fee multiplier.
 | 
			
		||||
        await testContract.updateProtocolFeeMultiplier.awaitTransactionSuccessAsync(protocolFeeMultiplier, {
 | 
			
		||||
            from: owner,
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    function randomOrder(fields?: Partial<Order>): Order {
 | 
			
		||||
@@ -96,6 +107,7 @@ blockchainTests('Exchange wrapper functions unit tests.', env => {
 | 
			
		||||
            takerAssetFilledAmount: order.takerAssetAmount,
 | 
			
		||||
            makerFeePaid: order.makerFee,
 | 
			
		||||
            takerFeePaid: order.takerFee,
 | 
			
		||||
            protocolFeePaid: protocolFeeMultiplier,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1309,50 +1321,5 @@ blockchainTests('Exchange wrapper functions unit tests.', env => {
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getOrdersInfo', () => {
 | 
			
		||||
        // Computes the expected (fake) order info generated by the `TestWrapperFunctions` contract.
 | 
			
		||||
        function getExpectedOrderInfo(order: Order): OrderInfo {
 | 
			
		||||
            const MAX_ORDER_STATUS = OrderStatus.Cancelled as number;
 | 
			
		||||
            return {
 | 
			
		||||
                orderHash: getExpectedOrderHash(order),
 | 
			
		||||
                // Lower uint128 of `order.salt` is the `orderTakerAssetFilledAmount`.
 | 
			
		||||
                orderTakerAssetFilledAmount: order.salt.mod(new BigNumber(2).pow(128)),
 | 
			
		||||
                // High byte of `order.salt` is the `orderStatus`.
 | 
			
		||||
                orderStatus:
 | 
			
		||||
                    order.salt.dividedToIntegerBy(new BigNumber(2).pow(248)).toNumber() % (MAX_ORDER_STATUS + 1),
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        it('works with no orders', async () => {
 | 
			
		||||
            const infos = await testContract.getOrdersInfo.callAsync([]);
 | 
			
		||||
            expect(infos.length).to.eq(0);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('works with one order', async () => {
 | 
			
		||||
            const orders = [randomOrder()];
 | 
			
		||||
            const expectedResult = orders.map(getExpectedOrderInfo);
 | 
			
		||||
            const actualResult = await testContract.getOrdersInfo.callAsync(orders);
 | 
			
		||||
            expect(actualResult).to.deep.eq(expectedResult);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('works with many orders', async () => {
 | 
			
		||||
            const NUM_ORDERS = 16;
 | 
			
		||||
            const orders = _.times(NUM_ORDERS, () => randomOrder());
 | 
			
		||||
            const expectedResult = orders.map(getExpectedOrderInfo);
 | 
			
		||||
            const actualResult = await testContract.getOrdersInfo.callAsync(orders);
 | 
			
		||||
            expect(actualResult).to.deep.eq(expectedResult);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('works with duplicate orders', async () => {
 | 
			
		||||
            const NUM_UNIQUE_ORDERS = 4;
 | 
			
		||||
            const CLONE_COUNT = 2;
 | 
			
		||||
            const uniqueOrders = _.times(NUM_UNIQUE_ORDERS, () => randomOrder());
 | 
			
		||||
            const orders = _.shuffle(_.flatten(_.times(CLONE_COUNT, () => uniqueOrders)));
 | 
			
		||||
            const expectedResult = orders.map(getExpectedOrderInfo);
 | 
			
		||||
            const actualResult = await testContract.getOrdersInfo.callAsync(orders);
 | 
			
		||||
            expect(actualResult).to.deep.eq(expectedResult);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
// tslint:disable-next-line: max-file-line-count
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,6 @@
 | 
			
		||||
        "generated-artifacts/MixinMatchOrders.json",
 | 
			
		||||
        "generated-artifacts/MixinProtocolFees.json",
 | 
			
		||||
        "generated-artifacts/MixinSignatureValidator.json",
 | 
			
		||||
        "generated-artifacts/MixinStakingManager.json",
 | 
			
		||||
        "generated-artifacts/MixinTransactions.json",
 | 
			
		||||
        "generated-artifacts/MixinTransferSimulator.json",
 | 
			
		||||
        "generated-artifacts/MixinWrapperFunctions.json",
 | 
			
		||||
 
 | 
			
		||||
@@ -21,37 +21,15 @@ pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
interface IStaking {
 | 
			
		||||
 | 
			
		||||
    /// @dev Pays several protocols fee in ETH.
 | 
			
		||||
    /// @param makers The addresses of the order makers.
 | 
			
		||||
    /// @param fees The fee amounts paid by each of the makers.
 | 
			
		||||
    function batchPayProtocolFees(
 | 
			
		||||
        address[] calldata makers,
 | 
			
		||||
        uint256[] calldata fees
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable;
 | 
			
		||||
 | 
			
		||||
    /// @dev Pays a protocol fee in ETH.
 | 
			
		||||
    /// @param makerAddress The address of the order's maker.
 | 
			
		||||
    function payProtocolFee(address makerAddress)
 | 
			
		||||
    /// @param payerAddress The address that is responsible for paying the protocol fee.
 | 
			
		||||
    /// @param protocolFeePaid The amount of protocol fees that should be paid.
 | 
			
		||||
    function payProtocolFee(
 | 
			
		||||
        address makerAddress,
 | 
			
		||||
        address payerAddress,
 | 
			
		||||
        uint256 protocolFeePaid
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable;
 | 
			
		||||
 | 
			
		||||
    /// @dev Records several protocol fees that were paid in WETH.
 | 
			
		||||
    /// @param makers The addresses of the order makers.
 | 
			
		||||
    /// @param fees The fee amounts paid by each of the makers.
 | 
			
		||||
    function batchRecordProtocolFees(
 | 
			
		||||
        address[] calldata makers,
 | 
			
		||||
        uint256[] calldata fees
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Records a protocol fee that was paid in WETH.
 | 
			
		||||
    /// @param makerAddress The address of the order's maker.
 | 
			
		||||
    /// @param fee The fee amount that was paid by the maker.
 | 
			
		||||
    function recordProtocolFee(
 | 
			
		||||
        address makerAddress,
 | 
			
		||||
        uint256 fee
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ contract Refundable {
 | 
			
		||||
    modifier refundFinalBalance {
 | 
			
		||||
        _;
 | 
			
		||||
        if (!shouldNotRefund) {
 | 
			
		||||
            msg.sender.transfer(address(this).balance);
 | 
			
		||||
            refundNonzeroBalance();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -38,7 +38,16 @@ contract Refundable {
 | 
			
		||||
            shouldNotRefund = true;
 | 
			
		||||
            _;
 | 
			
		||||
            shouldNotRefund = false;
 | 
			
		||||
            msg.sender.transfer(address(this).balance);
 | 
			
		||||
            refundNonzeroBalance();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function refundNonzeroBalance()
 | 
			
		||||
        internal
 | 
			
		||||
    {
 | 
			
		||||
        uint256 balance = address(this).balance;
 | 
			
		||||
        if (balance > 0) {
 | 
			
		||||
            msg.sender.transfer(balance);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,13 @@ import "../src/Refundable.sol";
 | 
			
		||||
contract TestRefundable is
 | 
			
		||||
    Refundable
 | 
			
		||||
{
 | 
			
		||||
    function refundNonzeroBalanceExternal()
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        refundNonzeroBalance();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setShouldNotRefund(bool shouldNotRefundNew)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -24,10 +24,33 @@ import "./TestRefundable.sol";
 | 
			
		||||
contract TestRefundableReceiver {
 | 
			
		||||
 | 
			
		||||
    /// @dev A payable fallback function is necessary to receive refunds from the `TestRefundable` contract.
 | 
			
		||||
    ///      This function ensures that zero value is not sent to the contract, which tests the feature of
 | 
			
		||||
    ///      of the `refundNonzeroBalance` that doesn't transfer if the balance is zero.
 | 
			
		||||
    function ()
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {} // solhint-disable-line no-empty-blocks
 | 
			
		||||
    {
 | 
			
		||||
        // Ensure that a value of zero was not transferred to the contract.
 | 
			
		||||
        require(msg.value != 0, "Zero value should not be sent to this contract.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This function tests the behavior of the `refundNonzeroBalance` function by checking whether or
 | 
			
		||||
    ///      not the `callCounter` state variable changes after the `refundNonzeroBalance` is called.
 | 
			
		||||
    /// @param testRefundable The TestRefundable that should be tested against.
 | 
			
		||||
    function testRefundNonzeroBalance(TestRefundable testRefundable)
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
    {
 | 
			
		||||
        // Call `refundNonzeroBalance()` and forward all of the eth sent to the contract.
 | 
			
		||||
        testRefundable.refundNonzeroBalanceExternal.value(msg.value)();
 | 
			
		||||
 | 
			
		||||
        // If the value sent was nonzero, a check that a refund was received will be executed. Otherwise, the fallback
 | 
			
		||||
        // function contains a check that will fail in the event that a value of zero was sent to the contract.
 | 
			
		||||
        if (msg.value > 0) {
 | 
			
		||||
            // Ensure that a full refund was provided to this contract.
 | 
			
		||||
            require(address(this).balance == msg.value, "A full refund was not provided by `refundNonzeroBalance`");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This function tests the behavior to a simple call to `refundFinalBalanceFunction`. This
 | 
			
		||||
    ///      test will verify that the correct refund was provided after the call (depending on whether
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { blockchainTests } from '@0x/contracts-test-utils';
 | 
			
		||||
import { blockchainTests, constants } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
@@ -8,6 +8,9 @@ blockchainTests('Refundable', env => {
 | 
			
		||||
    let refundable: TestRefundableContract;
 | 
			
		||||
    let receiver: TestRefundableReceiverContract;
 | 
			
		||||
 | 
			
		||||
    const ONE_HUNDRED = new BigNumber(100);
 | 
			
		||||
    const ONE_THOUSAND = new BigNumber(1000);
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        // Create the refundable contract.
 | 
			
		||||
        refundable = await TestRefundableContract.deployFrom0xArtifactAsync(
 | 
			
		||||
@@ -26,13 +29,32 @@ blockchainTests('Refundable', env => {
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // The contents of these typescript tests is not adequate to understand the assertions that are made during
 | 
			
		||||
    // these calls. For a more accurate picture, checkout out "./contracts/test/TestRefundableReceiver.sol". Specifically,
 | 
			
		||||
    // the function `testRefundNonzeroBalance()` is used in this test suite.
 | 
			
		||||
    blockchainTests.resets('refundNonzeroBalance', () => {
 | 
			
		||||
        it('should not send a refund when no value is sent', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded.
 | 
			
		||||
            await receiver.testRefundNonzeroBalance.awaitTransactionSuccessAsync(refundable.address, {
 | 
			
		||||
                value: constants.ZERO_AMOUNT,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should send a full refund when nonzero value is sent', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded.
 | 
			
		||||
            await receiver.testRefundNonzeroBalance.awaitTransactionSuccessAsync(refundable.address, {
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // The contents of these typescript tests is not adequate to understand the assertions that are made during
 | 
			
		||||
    // these calls. For a more accurate picture, checkout out "./contracts/test/TestRefundableReceiver.sol".
 | 
			
		||||
    blockchainTests.resets('refundFinalBalance', async () => {
 | 
			
		||||
    blockchainTests.resets('refundFinalBalance', () => {
 | 
			
		||||
        it('should fully refund the sender when `shouldNotRefund` is false', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testRefundFinalBalance.awaitTransactionSuccessAsync(refundable.address, false, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -40,7 +62,7 @@ blockchainTests('Refundable', env => {
 | 
			
		||||
        it('should fully refund the sender when `shouldNotRefund` is false for two calls in a row', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testRefundFinalBalance.awaitTransactionSuccessAsync(refundable.address, false, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Send 1000 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
@@ -59,11 +81,11 @@ blockchainTests('Refundable', env => {
 | 
			
		||||
 | 
			
		||||
    // The contents of these typescript tests is not adequate to understand the assertions that are made during
 | 
			
		||||
    // these calls. For a more accurate picture, checkout out "./contracts/test/TestRefundableReceiver.sol".
 | 
			
		||||
    blockchainTests.resets('disableRefundUntilEnd', async () => {
 | 
			
		||||
    blockchainTests.resets('disableRefundUntilEnd', () => {
 | 
			
		||||
        it('should fully refund the sender when `shouldNotRefund` is false', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testDisableRefundUntilEnd.awaitTransactionSuccessAsync(refundable.address, false, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -71,47 +93,47 @@ blockchainTests('Refundable', env => {
 | 
			
		||||
        it('should fully refund the sender when `shouldNotRefund` is false for two calls in a row', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testDisableRefundUntilEnd.awaitTransactionSuccessAsync(refundable.address, false, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Send 1000 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testDisableRefundUntilEnd.awaitTransactionSuccessAsync(refundable.address, false, {
 | 
			
		||||
                value: new BigNumber(1000),
 | 
			
		||||
                value: ONE_THOUSAND,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should not refund the sender if `shouldNotRefund` is true', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should not be refunded.
 | 
			
		||||
            await receiver.testDisableRefundUntilEnd.awaitTransactionSuccessAsync(refundable.address, false, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should disable the `disableRefundUntilEnd` modifier and refund when `shouldNotRefund` is false', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should be refunded.
 | 
			
		||||
            await receiver.testNestedDisableRefundUntilEnd.awaitTransactionSuccessAsync(refundable.address, false, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should disable the `refundFinalBalance` modifier and send no refund when `shouldNotRefund` is true', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should not be refunded.
 | 
			
		||||
            await receiver.testNestedDisableRefundUntilEnd.awaitTransactionSuccessAsync(refundable.address, true, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should disable the `refundFinalBalance` modifier and refund when `shouldNotRefund` is false', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should be refunded.
 | 
			
		||||
            await receiver.testMixedRefunds.awaitTransactionSuccessAsync(refundable.address, false, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should disable the `refundFinalBalance` modifier and send no refund when `shouldNotRefund` is true', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should not be refunded.
 | 
			
		||||
            await receiver.testMixedRefunds.awaitTransactionSuccessAsync(refundable.address, true, {
 | 
			
		||||
                value: new BigNumber(100),
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
export const constants = {
 | 
			
		||||
    RPC_URL: 'http://localhost:8545',
 | 
			
		||||
    RPC_PORT: 8545,
 | 
			
		||||
    GAS_LIMIT: 7000000,
 | 
			
		||||
    GAS_LIMIT: 8000000,
 | 
			
		||||
    TESTRPC_FIRST_ADDRESS: '0x5409ed021d9299bf6814279a6a1411a7e866a631',
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user