diff options
Diffstat (limited to 'packages/contracts')
15 files changed, 484 insertions, 138 deletions
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol index ec84b1e19..6f435892b 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinExchangeCore.sol @@ -154,6 +154,9 @@ contract MixinExchangeCore is // Compute the order hash orderInfo.orderHash = getOrderHash(order); + // Fetch filled amount + orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash]; + // If order.makerAssetAmount is zero, we also reject the order. // While the Exchange contract handles them correctly, they create // edge cases in the supporting infrastructure because they have @@ -172,6 +175,12 @@ contract MixinExchangeCore is return orderInfo; } + // Validate order availability + if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) { + orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED); + return orderInfo; + } + // Validate order expiration // solhint-disable-next-line not-rely-on-time if (block.timestamp >= order.expirationTimeSeconds) { @@ -189,13 +198,6 @@ contract MixinExchangeCore is return orderInfo; } - // Fetch filled amount and validate order availability - orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash]; - if (orderInfo.orderTakerAssetFilledAmount >= order.takerAssetAmount) { - orderInfo.orderStatus = uint8(OrderStatus.FULLY_FILLED); - return orderInfo; - } - // All other statuses are ruled out: order is Fillable orderInfo.orderStatus = uint8(OrderStatus.FILLABLE); return orderInfo; diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol index a16d2f897..d420f7e85 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol @@ -529,4 +529,20 @@ contract MixinWrapperFunctions is cancelOrder(orders[i]); } } + + /// @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 length = orders.length; + LibOrder.OrderInfo[] memory ordersInfo = new LibOrder.OrderInfo[](length); + for (uint256 i = 0; i < length; i++) { + ordersInfo[i] = getOrderInfo(orders[i]); + } + return ordersInfo; + } } diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol index ad7a56a06..56a533646 100644 --- a/packages/contracts/src/2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol +++ b/packages/contracts/src/2.0.0/protocol/Exchange/interfaces/IWrapperFunctions.sol @@ -149,4 +149,12 @@ 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); } diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts index d9f3851d1..1eb6f2a5c 100644 --- a/packages/contracts/test/exchange/core.ts +++ b/packages/contracts/test/exchange/core.ts @@ -15,13 +15,14 @@ import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_pr import { ExchangeCancelEventArgs, ExchangeContract } from '../../generated_contract_wrappers/exchange'; import { artifacts } from '../utils/artifacts'; import { expectTransactionFailedAsync } from '../utils/assertions'; +import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; import { OrderFactory } from '../utils/order_factory'; -import { ERC20BalancesByOwner } from '../utils/types'; +import { ERC20BalancesByOwner, OrderStatus } from '../utils/types'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); @@ -129,11 +130,11 @@ describe('Exchange core', () => { describe('fillOrder', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); }); it('should throw if signature is invalid', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), }); @@ -151,7 +152,7 @@ describe('Exchange core', () => { }); it('should throw if no value is filled', async () => { - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); return expectTransactionFailedAsync( exchangeWrapper.fillOrderAsync(signedOrder, takerAddress), @@ -163,7 +164,7 @@ describe('Exchange core', () => { describe('cancelOrder', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); }); it('should throw if not sent by maker', async () => { @@ -174,7 +175,7 @@ describe('Exchange core', () => { }); it('should throw if makerAssetAmount is 0', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(0), }); @@ -185,7 +186,7 @@ describe('Exchange core', () => { }); it('should throw if takerAssetAmount is 0', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(0), }); @@ -229,8 +230,9 @@ describe('Exchange core', () => { }); it('should throw if order is expired', async () => { - signedOrder = orderFactory.newSignedOrder({ - expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)), + const currentTimestamp = await getLatestBlockTimestampAsync(); + signedOrder = await orderFactory.newSignedOrderAsync({ + expirationTimeSeconds: new BigNumber(currentTimestamp).sub(10), }); return expectTransactionFailedAsync( exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress), @@ -239,7 +241,7 @@ describe('Exchange core', () => { }); it('should throw if rounding error is greater than 0.1%', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1001), takerAssetAmount: new BigNumber(3), }); @@ -288,22 +290,22 @@ describe('Exchange core', () => { // Since we cancelled with orderEpoch=1, orders with orderEpoch<=1 will not be processed erc20Balances = await erc20Wrapper.getBalancesAsync(); const signedOrders = [ - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18), salt: new BigNumber(0), }), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(79), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(79), 18), salt: new BigNumber(1), }), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(979), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(979), 18), salt: new BigNumber(2), }), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18), salt: new BigNumber(3), @@ -350,7 +352,7 @@ describe('Exchange core', () => { // Construct Exchange parameters const makerAssetId = erc721TakerAssetIds[0]; const takerAssetId = erc721TakerAssetIds[1]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -373,7 +375,7 @@ describe('Exchange core', () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetIds[0]; const takerAssetId = erc721MakerAssetIds[1]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -396,7 +398,7 @@ describe('Exchange core', () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetIds[0]; const takerAssetId = erc721TakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(2), takerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -419,7 +421,7 @@ describe('Exchange core', () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetIds[0]; const takerAssetId = erc721TakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(500), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -441,7 +443,7 @@ describe('Exchange core', () => { it('should throw on partial fill', async () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -462,7 +464,7 @@ describe('Exchange core', () => { const makerAssetData = assetProxyUtils .encodeERC721AssetData(erc721Token.address, makerAssetId) .slice(0, -2); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), makerAssetData, @@ -481,6 +483,124 @@ describe('Exchange core', () => { ); }); }); + + describe('getOrderInfo', () => { + beforeEach(async () => { + signedOrder = await orderFactory.newSignedOrderAsync(); + }); + it('should return the correct orderInfo for an unfilled valid order', async () => { + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.FILLABLE; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for a fully filled order', async () => { + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount; + const expectedOrderStatus = OrderStatus.FULLY_FILLED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for a partially filled order', async () => { + const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = takerAssetFillAmount; + const expectedOrderStatus = OrderStatus.FILLABLE; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for a cancelled and unfilled order', async () => { + await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.CANCELLED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for a cancelled and partially filled order', async () => { + const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = takerAssetFillAmount; + const expectedOrderStatus = OrderStatus.CANCELLED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an expired and unfilled order', async () => { + const currentTimestamp = await getLatestBlockTimestampAsync(); + const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); + await increaseTimeAndMineBlockAsync(timeUntilExpiration); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.EXPIRED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an expired and partially filled order', async () => { + const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); + const currentTimestamp = await getLatestBlockTimestampAsync(); + const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); + await increaseTimeAndMineBlockAsync(timeUntilExpiration); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = takerAssetFillAmount; + const expectedOrderStatus = OrderStatus.EXPIRED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an expired and fully filled order', async () => { + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); + const currentTimestamp = await getLatestBlockTimestampAsync(); + const timeUntilExpiration = signedOrder.expirationTimeSeconds.minus(currentTimestamp).toNumber(); + await increaseTimeAndMineBlockAsync(timeUntilExpiration); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = signedOrder.takerAssetAmount; + // FULLY_FILLED takes precedence over EXPIRED + const expectedOrderStatus = OrderStatus.FULLY_FILLED; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an order with a makerAssetAmount of 0', async () => { + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(0) }); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.INVALID_MAKER_ASSET_AMOUNT; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + it('should return the correct orderInfo for an order with a takerAssetAmount of 0', async () => { + signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(0) }); + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = new BigNumber(0); + const expectedOrderStatus = OrderStatus.INVALID_TAKER_ASSET_AMOUNT; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); }); // tslint:disable:max-file-line-count // tslint:enable:no-unnecessary-type-assertion diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts index 6ded6329c..af595fedd 100644 --- a/packages/contracts/test/exchange/libs.ts +++ b/packages/contracts/test/exchange/libs.ts @@ -71,7 +71,7 @@ describe('Exchange libs', () => { }); describe('getOrderHash', () => { it('should output the correct orderHash', async () => { - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); const orderHashHex = await libs.publicGetOrderHash.callAsync(signedOrder); expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex); }); diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts index 16041e968..6975aa115 100644 --- a/packages/contracts/test/exchange/match_orders.ts +++ b/packages/contracts/test/exchange/match_orders.ts @@ -150,13 +150,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when orders completely fill each other', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -182,13 +182,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when orders completely fill each other and taker doesnt take a profit', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -225,13 +225,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when left order is completely filled and right order is partially filled', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -257,13 +257,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when right order is completely filled and left order is partially filled', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -289,13 +289,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts when consecutive calls are used to completely fill the left order', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -326,7 +326,7 @@ describe('matchOrders', () => { // Note: This order needs makerAssetAmount=90/takerAssetAmount=[anything <= 45] to fully fill the right order. // However, we use 100/50 to ensure a partial fill as we want to go down the "left fill" // branch in the contract twice for this test. - const signedOrderRight2 = orderFactoryRight.newSignedOrder({ + const signedOrderRight2 = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -356,14 +356,14 @@ describe('matchOrders', () => { it('should transfer the correct amounts when consecutive calls are used to completely fill the right order', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -394,7 +394,7 @@ describe('matchOrders', () => { // Note: This order needs makerAssetAmount=96/takerAssetAmount=48 to fully fill the right order. // However, we use 100/50 to ensure a partial fill as we want to go down the "right fill" // branch in the contract twice for this test. - const signedOrderLeft2 = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft2 = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18), @@ -425,13 +425,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if fee recipient is the same across both matched orders', async () => { const feeRecipientAddress = feeRecipientAddressLeft; - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -451,13 +451,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if taker is also the left order maker', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -478,13 +478,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if taker is also the right order maker', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -505,13 +505,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if taker is also the left fee recipient', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -532,13 +532,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if taker is also the right fee recipient', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -559,13 +559,13 @@ describe('matchOrders', () => { it('should transfer the correct amounts if left maker is the left fee recipient and right maker is the right fee recipient', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: makerAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -585,13 +585,13 @@ describe('matchOrders', () => { it('Should throw if left order is not fillable', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -610,13 +610,13 @@ describe('matchOrders', () => { it('Should throw if right order is not fillable', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -635,13 +635,13 @@ describe('matchOrders', () => { it('should throw if there is not a positive spread', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -658,13 +658,13 @@ describe('matchOrders', () => { it('should throw if the left maker asset is not equal to the right taker asset ', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), @@ -685,7 +685,7 @@ describe('matchOrders', () => { it('should throw if the right maker asset is not equal to the left taker asset', async () => { // Create orders to match - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -693,7 +693,7 @@ describe('matchOrders', () => { takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), @@ -711,7 +711,7 @@ describe('matchOrders', () => { it('should transfer correct amounts when left order maker asset is an ERC721 token', async () => { // Create orders to match const erc721TokenToTransfer = erc721LeftMakerAssetIds[0]; - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), @@ -719,7 +719,7 @@ describe('matchOrders', () => { takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), @@ -746,7 +746,7 @@ describe('matchOrders', () => { it('should transfer correct amounts when right order maker asset is an ERC721 token', async () => { // Create orders to match const erc721TokenToTransfer = erc721RightMakerAssetIds[0]; - const signedOrderLeft = orderFactoryLeft.newSignedOrder({ + const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ makerAddress: makerAddressLeft, makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), @@ -754,7 +754,7 @@ describe('matchOrders', () => { takerAssetAmount: new BigNumber(1), feeRecipientAddress: feeRecipientAddressLeft, }); - const signedOrderRight = orderFactoryRight.newSignedOrder({ + const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ makerAddress: makerAddressRight, makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer), takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts index 8cd6409a5..2f4a9055d 100644 --- a/packages/contracts/test/exchange/signature_validator.ts +++ b/packages/contracts/test/exchange/signature_validator.ts @@ -95,7 +95,7 @@ describe('MixinSignatureValidator', () => { describe('isValidSignature', () => { beforeEach(async () => { - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); }); it('should revert when signature is empty', async () => { diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts index 0d66b11b8..831576cd2 100644 --- a/packages/contracts/test/exchange/transactions.ts +++ b/packages/contracts/test/exchange/transactions.ts @@ -121,7 +121,7 @@ describe('Exchange transactions', () => { let takerAssetFillAmount: BigNumber; beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder); takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); @@ -226,7 +226,7 @@ describe('Exchange transactions', () => { it("should cancel an order if called from the order's sender", async () => { const orderSalt = new BigNumber(0); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ senderAddress: exchangeWrapperContract.address, salt: orderSalt, }); @@ -265,7 +265,7 @@ describe('Exchange transactions', () => { it("should not cancel an order if not called from the order's sender", async () => { const orderSalt = new BigNumber(0); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ senderAddress: exchangeWrapperContract.address, salt: orderSalt, }); @@ -356,7 +356,7 @@ describe('Exchange transactions', () => { }); beforeEach(async () => { - signedOrder = whitelistOrderFactory.newSignedOrder(); + signedOrder = await whitelistOrderFactory.newSignedOrderAsync(); erc20Balances = await erc20Wrapper.getBalancesAsync(); }); diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts index 655d55b83..abcb8364a 100644 --- a/packages/contracts/test/exchange/wrapper.ts +++ b/packages/contracts/test/exchange/wrapper.ts @@ -1,5 +1,5 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils'; -import { assetProxyUtils } from '@0xproject/order-utils'; +import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils'; import { RevertReason, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; @@ -13,13 +13,14 @@ import { ERC721ProxyContract } from '../../generated_contract_wrappers/erc721_pr import { ExchangeContract } from '../../generated_contract_wrappers/exchange'; import { artifacts } from '../utils/artifacts'; import { expectTransactionFailedAsync } from '../utils/assertions'; +import { getLatestBlockTimestampAsync, increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper'; import { OrderFactory } from '../utils/order_factory'; -import { ERC20BalancesByOwner } from '../utils/types'; +import { ERC20BalancesByOwner, OrderStatus } from '../utils/types'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; chaiSetup.configure(); @@ -126,7 +127,7 @@ describe('Exchange wrappers', () => { }); describe('fillOrKillOrder', () => { it('should transfer the correct amounts', async () => { - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); @@ -170,8 +171,9 @@ describe('Exchange wrappers', () => { }); it('should throw if a signedOrder is expired', async () => { - const signedOrder = orderFactory.newSignedOrder({ - expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)), + const currentTimestamp = await getLatestBlockTimestampAsync(); + const signedOrder = await orderFactory.newSignedOrderAsync({ + expirationTimeSeconds: new BigNumber(currentTimestamp).sub(10), }); return expectTransactionFailedAsync( @@ -181,7 +183,7 @@ describe('Exchange wrappers', () => { }); it('should throw if entire takerAssetFillAmount not filled', async () => { - const signedOrder = orderFactory.newSignedOrder(); + const signedOrder = await orderFactory.newSignedOrderAsync(); await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount: signedOrder.takerAssetAmount.div(2), @@ -196,7 +198,7 @@ describe('Exchange wrappers', () => { describe('fillOrderNoThrow', () => { it('should transfer the correct amounts', async () => { - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), }); @@ -245,7 +247,7 @@ describe('Exchange wrappers', () => { }); it('should not change erc20Balances if maker erc20Balances are too low to fill order', async () => { - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), }); @@ -255,7 +257,7 @@ describe('Exchange wrappers', () => { }); it('should not change erc20Balances if taker erc20Balances are too low to fill order', async () => { - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), }); @@ -265,7 +267,7 @@ describe('Exchange wrappers', () => { }); it('should not change erc20Balances if maker allowances are too low to fill order', async () => { - const signedOrder = orderFactory.newSignedOrder(); + const signedOrder = await orderFactory.newSignedOrderAsync(); await web3Wrapper.awaitTransactionSuccessAsync( await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { from: makerAddress, @@ -285,7 +287,7 @@ describe('Exchange wrappers', () => { }); it('should not change erc20Balances if taker allowances are too low to fill order', async () => { - const signedOrder = orderFactory.newSignedOrder(); + const signedOrder = await orderFactory.newSignedOrderAsync(); await web3Wrapper.awaitTransactionSuccessAsync( await erc20TokenB.approve.sendTransactionAsync(erc20Proxy.address, new BigNumber(0), { from: takerAddress, @@ -306,7 +308,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if makerAssetAddress is ZRX, makerAssetAmount + makerFee > maker balance', async () => { const makerZRXBalance = new BigNumber(erc20Balances[makerAddress][zrxToken.address]); - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: makerZRXBalance, makerFee: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -318,7 +320,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if makerAssetAddress is ZRX, makerAssetAmount + makerFee > maker allowance', async () => { const makerZRXAllowance = await zrxToken.allowance.callAsync(makerAddress, erc20Proxy.address); - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(makerZRXAllowance), makerFee: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -330,7 +332,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if takerAssetAddress is ZRX, takerAssetAmount + takerFee > taker balance', async () => { const takerZRXBalance = new BigNumber(erc20Balances[takerAddress][zrxToken.address]); - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: takerZRXBalance, takerFee: new BigNumber(1), takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -342,7 +344,7 @@ describe('Exchange wrappers', () => { it('should not change erc20Balances if takerAssetAddress is ZRX, takerAssetAmount + takerFee > taker allowance', async () => { const takerZRXAllowance = await zrxToken.allowance.callAsync(takerAddress, erc20Proxy.address); - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ takerAssetAmount: new BigNumber(takerZRXAllowance), takerFee: new BigNumber(1), takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -356,7 +358,7 @@ describe('Exchange wrappers', () => { // Construct Exchange parameters const makerAssetId = erc721MakerAssetId; const takerAssetId = erc721TakerAssetId; - const signedOrder = orderFactory.newSignedOrder({ + const signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -388,9 +390,9 @@ describe('Exchange wrappers', () => { let signedOrders: SignedOrder[]; beforeEach(async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), ]; }); @@ -696,11 +698,11 @@ describe('Exchange wrappers', () => { it('should throw when a signedOrder does not use the same takerAssetAddress', async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync({ takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), - orderFactory.newSignedOrder(), + await orderFactory.newSignedOrderAsync(), ]; return expectTransactionFailedAsync( @@ -796,9 +798,9 @@ describe('Exchange wrappers', () => { it('should not fill a signedOrder that does not use the same takerAssetAddress', async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync({ takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), ]; @@ -914,11 +916,11 @@ describe('Exchange wrappers', () => { it('should throw when a signedOrder does not use the same makerAssetAddress', async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), - orderFactory.newSignedOrder(), + await orderFactory.newSignedOrderAsync(), ]; return expectTransactionFailedAsync( @@ -1012,9 +1014,9 @@ describe('Exchange wrappers', () => { it('should not fill a signedOrder that does not use the same makerAssetAddress', async () => { signedOrders = [ - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder(), - orderFactory.newSignedOrder({ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), }), ]; @@ -1069,5 +1071,189 @@ describe('Exchange wrappers', () => { expect(erc20Balances).to.be.deep.equal(newBalances); }); }); + + 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.FULLY_FILLED; + 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.FULLY_FILLED; + 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 diff --git a/packages/contracts/test/forwarder/forwarder.ts b/packages/contracts/test/forwarder/forwarder.ts index f0bf6ac03..4075fccad 100644 --- a/packages/contracts/test/forwarder/forwarder.ts +++ b/packages/contracts/test/forwarder/forwarder.ts @@ -148,14 +148,14 @@ describe(ContractName.Forwarder, () => { await blockchainLifecycle.startAsync(); feeProportion = 0; erc20Balances = await erc20Wrapper.getBalancesAsync(); - signedOrder = orderFactory.newSignedOrder(); + signedOrder = await orderFactory.newSignedOrderAsync(); signedOrders = [signedOrder]; - feeOrder = orderFactory.newSignedOrder({ + feeOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); feeOrders = [feeOrder]; - orderWithFee = orderFactory.newSignedOrder({ + orderWithFee = await orderFactory.newSignedOrderAsync({ takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); signedOrdersWithFee = [orderWithFee]; @@ -238,7 +238,7 @@ describe(ContractName.Forwarder, () => { expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0)); }); it('should fill the order when token is ZRX with fees', async () => { - orderWithFee = orderFactory.newSignedOrder({ + orderWithFee = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); @@ -260,7 +260,7 @@ describe(ContractName.Forwarder, () => { expect(newBalances[forwarderContract.address][weth.address]).to.be.bignumber.equal(new BigNumber(0)); }); it('should fail if sent an ETH amount too high', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); @@ -274,11 +274,11 @@ describe(ContractName.Forwarder, () => { ); }); it('should fail if fee abstraction amount is too high', async () => { - orderWithFee = orderFactory.newSignedOrder({ + orderWithFee = await orderFactory.newSignedOrderAsync({ takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), DECIMALS_DEFAULT), }); signedOrdersWithFee = [orderWithFee]; - feeOrder = orderFactory.newSignedOrder({ + feeOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); @@ -294,11 +294,11 @@ describe(ContractName.Forwarder, () => { }); it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => { const makerAssetId = erc721MakerAssetIds[0]; - const erc721SignedOrder = orderFactory.newSignedOrder({ + const erc721SignedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); - const erc20SignedOrder = orderFactory.newSignedOrder(); + const erc20SignedOrder = await orderFactory.newSignedOrderAsync(); signedOrders = [erc20SignedOrder, erc721SignedOrder]; const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount); return expectTransactionFailedAsync( @@ -418,7 +418,7 @@ describe(ContractName.Forwarder, () => { expect(takerBalanceAfter).to.be.bignumber.eq(takerBalanceBefore.plus(makerAssetAmount)); }); it('should buy the exact amount of assets when buying zrx with fee abstraction', async () => { - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), }); @@ -447,7 +447,7 @@ describe(ContractName.Forwarder, () => { expect(takerWeiBalanceAfter).to.be.bignumber.equal(takerWeiBalanceBefore.minus(expectedCostAfterGas)); }); it('throws if fees are higher than 5% when buying zrx', async () => { - const highFeeZRXOrder = orderFactory.newSignedOrder({ + const highFeeZRXOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), makerAssetAmount: signedOrder.makerAssetAmount, takerFee: signedOrder.makerAssetAmount.times(0.06), @@ -470,7 +470,7 @@ describe(ContractName.Forwarder, () => { ); }); it('throws if fees are higher than 5% when buying erc20', async () => { - const highFeeERC20Order = orderFactory.newSignedOrder({ + const highFeeERC20Order = await orderFactory.newSignedOrderAsync({ takerFee: signedOrder.makerAssetAmount.times(0.06), }); signedOrdersWithFee = [highFeeERC20Order]; @@ -544,7 +544,7 @@ describe(ContractName.Forwarder, () => { describe('marketBuyTokensWithEth - ERC721', async () => { it('buys ERC721 assets', async () => { const makerAssetId = erc721MakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); @@ -566,7 +566,7 @@ describe(ContractName.Forwarder, () => { }); it('buys ERC721 assets with fee abstraction', async () => { const makerAssetId = erc721MakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -588,7 +588,7 @@ describe(ContractName.Forwarder, () => { }); it('buys ERC721 assets with fee abstraction and pays fee to fee recipient', async () => { const makerAssetId = erc721MakerAssetIds[0]; - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), @@ -630,12 +630,12 @@ describe(ContractName.Forwarder, () => { it('buys multiple ERC721 assets with fee abstraction and pays fee to fee recipient', async () => { const makerAssetId1 = erc721MakerAssetIds[0]; const makerAssetId2 = erc721MakerAssetIds[1]; - const signedOrder1 = orderFactory.newSignedOrder({ + const signedOrder1 = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(3), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId1), }); - const signedOrder2 = orderFactory.newSignedOrder({ + const signedOrder2 = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId2), @@ -665,20 +665,20 @@ describe(ContractName.Forwarder, () => { // There are two fee orders, but the first fee order is partially filled while // the Forwarding contract tx is in the mempool. const erc721MakerAssetAmount = new BigNumber(1); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: erc721MakerAssetAmount, takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); signedOrders = [signedOrder]; - const firstFeeOrder = orderFactory.newSignedOrder({ + const firstFeeOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT), }); - const secondFeeOrder = orderFactory.newSignedOrder({ + const secondFeeOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -729,7 +729,7 @@ describe(ContractName.Forwarder, () => { // There are two fee orders, but the first fee order is partially filled while // the Forwarding contract tx is in the mempool. const erc721MakerAssetAmount = new BigNumber(1); - signedOrder = orderFactory.newSignedOrder({ + signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: erc721MakerAssetAmount, takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), DECIMALS_DEFAULT), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(6), DECIMALS_DEFAULT), @@ -737,13 +737,13 @@ describe(ContractName.Forwarder, () => { }); const zrxMakerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(8), DECIMALS_DEFAULT); signedOrders = [signedOrder]; - const firstFeeOrder = orderFactory.newSignedOrder({ + const firstFeeOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: zrxMakerAssetAmount, takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.1), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), DECIMALS_DEFAULT), }); - const secondFeeOrder = orderFactory.newSignedOrder({ + const secondFeeOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: zrxMakerAssetAmount, takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(0.12), DECIMALS_DEFAULT), makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address), @@ -778,11 +778,11 @@ describe(ContractName.Forwarder, () => { }); it('throws when mixed ERC721 and ERC20 assets', async () => { const makerAssetId = erc721MakerAssetIds[0]; - const erc721SignedOrder = orderFactory.newSignedOrder({ + const erc721SignedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); - const erc20SignedOrder = orderFactory.newSignedOrder(); + const erc20SignedOrder = await orderFactory.newSignedOrderAsync(); signedOrders = [erc721SignedOrder, erc20SignedOrder]; const makerAssetAmount = new BigNumber(signedOrders.length); const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount); @@ -796,11 +796,11 @@ describe(ContractName.Forwarder, () => { }); it('throws when mixed ERC721 and ERC20 assets with ERC20 first', async () => { const makerAssetId = erc721MakerAssetIds[0]; - const erc721SignedOrder = orderFactory.newSignedOrder({ + const erc721SignedOrder = await orderFactory.newSignedOrderAsync({ makerAssetAmount: new BigNumber(1), makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), }); - const erc20SignedOrder = orderFactory.newSignedOrder(); + const erc20SignedOrder = await orderFactory.newSignedOrderAsync(); signedOrders = [erc20SignedOrder, erc721SignedOrder]; const makerAssetAmount = new BigNumber(signedOrders.length); const fillAmountWei = erc20SignedOrder.takerAssetAmount.plus(erc721SignedOrder.takerAssetAmount); diff --git a/packages/contracts/test/multisig/asset_proxy_owner.ts b/packages/contracts/test/multisig/asset_proxy_owner.ts index 6a9843153..6b98605d3 100644 --- a/packages/contracts/test/multisig/asset_proxy_owner.ts +++ b/packages/contracts/test/multisig/asset_proxy_owner.ts @@ -18,9 +18,9 @@ import { expectContractCreationFailedWithoutReason, expectTransactionFailedWithoutReasonAsync, } from '../utils/assertions'; +import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; -import { increaseTimeAndMineBlockAsync } from '../utils/increase_time'; import { MultiSigWrapper } from '../utils/multi_sig_wrapper'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; diff --git a/packages/contracts/test/multisig/multi_sig_with_time_lock.ts b/packages/contracts/test/multisig/multi_sig_with_time_lock.ts index a8e9243a9..8eeeeca6b 100644 --- a/packages/contracts/test/multisig/multi_sig_with_time_lock.ts +++ b/packages/contracts/test/multisig/multi_sig_with_time_lock.ts @@ -9,9 +9,9 @@ import { } from '../../generated_contract_wrappers/multi_sig_wallet_with_time_lock'; import { artifacts } from '../utils/artifacts'; import { expectTransactionFailedWithoutReasonAsync } from '../utils/assertions'; +import { increaseTimeAndMineBlockAsync } from '../utils/block_timestamp'; import { chaiSetup } from '../utils/chai_setup'; import { constants } from '../utils/constants'; -import { increaseTimeAndMineBlockAsync } from '../utils/increase_time'; import { MultiSigWrapper } from '../utils/multi_sig_wrapper'; import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper'; diff --git a/packages/contracts/test/utils/increase_time.ts b/packages/contracts/test/utils/block_timestamp.ts index 4565d8dbc..1159792c4 100644 --- a/packages/contracts/test/utils/increase_time.ts +++ b/packages/contracts/test/utils/block_timestamp.ts @@ -29,3 +29,12 @@ export async function increaseTimeAndMineBlockAsync(seconds: number): Promise<nu return offset; } + +/** + * Returns the timestamp of the latest block in seconds since the Unix epoch. + * @returns a new Promise which will resolve with the timestamp in seconds. + */ +export async function getLatestBlockTimestampAsync(): Promise<number> { + const currentBlock = await web3Wrapper.getBlockAsync('latest'); + return currentBlock.timestamp; +} diff --git a/packages/contracts/test/utils/exchange_wrapper.ts b/packages/contracts/test/utils/exchange_wrapper.ts index be0b32c62..490ea959b 100644 --- a/packages/contracts/test/utils/exchange_wrapper.ts +++ b/packages/contracts/test/utils/exchange_wrapper.ts @@ -223,6 +223,10 @@ export class ExchangeWrapper { const orderInfo = (await this._exchange.getOrderInfo.callAsync(signedOrder)) as OrderInfo; return orderInfo; } + public async getOrdersInfoAsync(signedOrders: SignedOrder[]): Promise<OrderInfo[]> { + const ordersInfo = (await this._exchange.getOrdersInfo.callAsync(signedOrders)) as OrderInfo[]; + return ordersInfo; + } public async matchOrdersAsync( signedOrderLeft: SignedOrder, signedOrderRight: SignedOrder, diff --git a/packages/contracts/test/utils/order_factory.ts b/packages/contracts/test/utils/order_factory.ts index da418fa0f..63a893695 100644 --- a/packages/contracts/test/utils/order_factory.ts +++ b/packages/contracts/test/utils/order_factory.ts @@ -2,6 +2,7 @@ import { generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils import { Order, SignatureType, SignedOrder } from '@0xproject/types'; import { BigNumber } from '@0xproject/utils'; +import { getLatestBlockTimestampAsync } from './block_timestamp'; import { constants } from './constants'; import { signingUtils } from './signing_utils'; @@ -12,15 +13,15 @@ export class OrderFactory { this._defaultOrderParams = defaultOrderParams; this._privateKey = privateKey; } - public newSignedOrder( + public async newSignedOrderAsync( customOrderParams: Partial<Order> = {}, signatureType: SignatureType = SignatureType.EthSign, - ): SignedOrder { - const tenMinutes = 10 * 60 * 1000; - const randomExpiration = new BigNumber(Date.now() + tenMinutes); + ): Promise<SignedOrder> { + const tenMinutesInSeconds = 10 * 60; + const currentBlockTimestamp = await getLatestBlockTimestampAsync(); const order = ({ senderAddress: constants.NULL_ADDRESS, - expirationTimeSeconds: randomExpiration, + expirationTimeSeconds: new BigNumber(currentBlockTimestamp).add(tenMinutesInSeconds), salt: generatePseudoRandomSalt(), takerAddress: constants.NULL_ADDRESS, ...this._defaultOrderParams, |