From 5a45bc5e7ba3945fe5788b7f86f885768f034f4b Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 13 Dec 2018 11:10:24 -0800 Subject: Revert version bump to unpublished contracts packages --- contracts/extensions/package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/package.json b/contracts/extensions/package.json index e359f1e4d..0f82317e6 100644 --- a/contracts/extensions/package.json +++ b/contracts/extensions/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@0x/contracts-extensions", - "version": "1.0.1", + "version": "1.0.0", "engines": { "node": ">=6.12" }, @@ -45,7 +45,7 @@ "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md", "devDependencies": { "@0x/abi-gen": "^1.0.18", - "@0x/contracts-test-utils": "^1.0.1", + "@0x/contracts-test-utils": "^1.0.0", "@0x/dev-utils": "^1.0.20", "@0x/sol-compiler": "^1.1.15", "@0x/sol-cov": "^2.1.15", @@ -72,11 +72,11 @@ }, "dependencies": { "@0x/base-contract": "^3.0.9", - "@0x/contracts-interfaces": "^1.0.1", - "@0x/contracts-libs": "^1.0.1", + "@0x/contracts-interfaces": "^1.0.0", + "@0x/contracts-libs": "^1.0.0", "@0x/contracts-protocol": "^2.1.57", - "@0x/contracts-tokens": "^1.0.1", - "@0x/contracts-utils": "^1.0.1", + "@0x/contracts-tokens": "^1.0.0", + "@0x/contracts-utils": "^1.0.0", "@0x/order-utils": "^3.0.6", "@0x/types": "^1.4.0", "@0x/typescript-typings": "^3.0.5", -- cgit v1.2.3 From f8e84260b59c367d4f99c03b69b7c63a42735116 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 13 Dec 2018 11:33:55 -0800 Subject: Bump contracts-test-utils version to match the one on npm --- contracts/extensions/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/package.json b/contracts/extensions/package.json index 0f82317e6..b12184c45 100644 --- a/contracts/extensions/package.json +++ b/contracts/extensions/package.json @@ -45,7 +45,7 @@ "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md", "devDependencies": { "@0x/abi-gen": "^1.0.18", - "@0x/contracts-test-utils": "^1.0.0", + "@0x/contracts-test-utils": "^1.0.1", "@0x/dev-utils": "^1.0.20", "@0x/sol-compiler": "^1.1.15", "@0x/sol-cov": "^2.1.15", -- cgit v1.2.3 From 2abd8fe4ee860e5a4008a9f92f6d29239d14b2bc Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 13 Dec 2018 14:28:27 -0800 Subject: Publish - 0x.js@2.0.8 - @0x/abi-gen@1.0.19 - @0x/abi-gen-wrappers@2.0.2 - @0x/assert@1.0.20 - @0x/asset-buyer@3.0.4 - @0x/base-contract@3.0.10 - @0x/connect@3.0.10 - @0x/contract-wrappers@4.1.3 - @0x/dev-tools-pages@0.0.10 - @0x/dev-utils@1.0.21 - ethereum-types@1.1.4 - @0x/fill-scenarios@1.0.16 - @0x/instant@1.0.4 - @0x/json-schemas@2.1.4 - @0x/metacoin@0.0.32 - @0x/migrations@2.2.2 - @0x/order-utils@3.0.7 - @0x/order-watcher@2.2.8 - @0x/pipeline@1.0.2 - @0x/react-docs@1.0.22 - @0x/react-shared@1.0.25 - @0x/sol-compiler@1.1.16 - @0x/sol-cov@2.1.16 - @0x/sol-doc@1.0.11 - @0x/sol-resolver@1.1.1 - @0x/sra-spec@1.0.13 - @0x/subproviders@2.1.8 - @0x/testnet-faucets@1.0.60 - @0x/tslint-config@2.0.0 - @0x/types@1.4.1 - @0x/typescript-typings@3.0.6 - @0x/utils@2.0.8 - @0x/web3-wrapper@3.2.1 - @0x/website@0.0.63 - @0x/contracts-examples@1.0.1 - @0x/contracts-extensions@1.0.1 - @0x/contracts-interfaces@1.0.1 - @0x/contracts-libs@1.0.1 - @0x/contracts-multisig@1.0.1 - @0x/contracts-protocol@2.1.58 - @0x/contracts-test-utils@1.0.2 - @0x/contracts-tokens@1.0.1 - @0x/contracts-utils@1.0.1 --- contracts/extensions/package.json | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/package.json b/contracts/extensions/package.json index b12184c45..3b7e4f5f0 100644 --- a/contracts/extensions/package.json +++ b/contracts/extensions/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@0x/contracts-extensions", - "version": "1.0.0", + "version": "1.0.1", "engines": { "node": ">=6.12" }, @@ -44,13 +44,13 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md", "devDependencies": { - "@0x/abi-gen": "^1.0.18", - "@0x/contracts-test-utils": "^1.0.1", - "@0x/dev-utils": "^1.0.20", - "@0x/sol-compiler": "^1.1.15", - "@0x/sol-cov": "^2.1.15", - "@0x/subproviders": "^2.1.7", - "@0x/tslint-config": "^1.0.10", + "@0x/abi-gen": "^1.0.19", + "@0x/contracts-test-utils": "^1.0.2", + "@0x/dev-utils": "^1.0.21", + "@0x/sol-compiler": "^1.1.16", + "@0x/sol-cov": "^2.1.16", + "@0x/subproviders": "^2.1.8", + "@0x/tslint-config": "^2.0.0", "@types/bn.js": "^4.11.0", "@types/lodash": "4.14.104", "@types/node": "*", @@ -71,20 +71,20 @@ "yargs": "^10.0.3" }, "dependencies": { - "@0x/base-contract": "^3.0.9", - "@0x/contracts-interfaces": "^1.0.0", - "@0x/contracts-libs": "^1.0.0", - "@0x/contracts-protocol": "^2.1.57", - "@0x/contracts-tokens": "^1.0.0", - "@0x/contracts-utils": "^1.0.0", - "@0x/order-utils": "^3.0.6", - "@0x/types": "^1.4.0", - "@0x/typescript-typings": "^3.0.5", - "@0x/utils": "^2.0.7", - "@0x/web3-wrapper": "^3.2.0", + "@0x/base-contract": "^3.0.10", + "@0x/contracts-interfaces": "^1.0.1", + "@0x/contracts-libs": "^1.0.1", + "@0x/contracts-protocol": "^2.1.58", + "@0x/contracts-tokens": "^1.0.1", + "@0x/contracts-utils": "^1.0.1", + "@0x/order-utils": "^3.0.7", + "@0x/types": "^1.4.1", + "@0x/typescript-typings": "^3.0.6", + "@0x/utils": "^2.0.8", + "@0x/web3-wrapper": "^3.2.1", "@types/js-combinatorics": "^0.5.29", "bn.js": "^4.11.8", - "ethereum-types": "^1.1.3", + "ethereum-types": "^1.1.4", "ethereumjs-util": "^5.1.1", "lodash": "^4.17.5" }, -- cgit v1.2.3 From 545101f7a5155fed77f9c65153bd13bdc23387bf Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 13 Dec 2018 14:36:34 -0800 Subject: Make contracts packages not private --- contracts/extensions/package.json | 1 - 1 file changed, 1 deletion(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/package.json b/contracts/extensions/package.json index 3b7e4f5f0..7a200455b 100644 --- a/contracts/extensions/package.json +++ b/contracts/extensions/package.json @@ -1,5 +1,4 @@ { - "private": true, "name": "@0x/contracts-extensions", "version": "1.0.1", "engines": { -- cgit v1.2.3 From 59fad5845c9eb9ed66ecb992a70f705772e2be76 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 13 Dec 2018 14:43:40 -0800 Subject: Move Forwarder CHANGELOG entries to extensions CHANGELOG --- contracts/extensions/CHANGELOG.json | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 contracts/extensions/CHANGELOG.json (limited to 'contracts/extensions') diff --git a/contracts/extensions/CHANGELOG.json b/contracts/extensions/CHANGELOG.json new file mode 100644 index 000000000..1c181d623 --- /dev/null +++ b/contracts/extensions/CHANGELOG.json @@ -0,0 +1,31 @@ +[ + { + "name": "Forwarder", + "version": "1.1.0", + "changes": [ + { + "note": "Round up when calculating remaining amounts in marketBuy functions", + "pr": 1162, + "networks": { + "1": "0x5468a1dc173652ee28d249c271fa9933144746b1", + "3": "0x2240dab907db71e64d3e0dba4800c83b5c502d4e", + "42": "0x17992e4ffb22730138e4b62aaa6367fa9d3699a6" + } + } + ] + }, + { + "name": "Forwarder", + "version": "1.0.0", + "changes": [ + { + "note": "protocol v2 deploy", + "networks": { + "1": "0x7afc2d5107af94c462a194d2c21b5bdd238709d6", + "3": "0x3983e204b12b3c02fb0638caf2cd406a62e0ead3", + "42": "0xd85e2fa7e7e252b27b01bf0d65c946959d2f45b8" + } + } + ] + } +] \ No newline at end of file -- cgit v1.2.3 From d5e15b05fbeb520519fca7ae3063b950db2b2e2c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 13 Dec 2018 14:49:58 -0800 Subject: Rename contracts CHANGELOGs to DEPLOYs --- contracts/extensions/CHANGELOG.json | 31 ------------------------------- contracts/extensions/DEPLOYS.json | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 31 deletions(-) delete mode 100644 contracts/extensions/CHANGELOG.json create mode 100644 contracts/extensions/DEPLOYS.json (limited to 'contracts/extensions') diff --git a/contracts/extensions/CHANGELOG.json b/contracts/extensions/CHANGELOG.json deleted file mode 100644 index 1c181d623..000000000 --- a/contracts/extensions/CHANGELOG.json +++ /dev/null @@ -1,31 +0,0 @@ -[ - { - "name": "Forwarder", - "version": "1.1.0", - "changes": [ - { - "note": "Round up when calculating remaining amounts in marketBuy functions", - "pr": 1162, - "networks": { - "1": "0x5468a1dc173652ee28d249c271fa9933144746b1", - "3": "0x2240dab907db71e64d3e0dba4800c83b5c502d4e", - "42": "0x17992e4ffb22730138e4b62aaa6367fa9d3699a6" - } - } - ] - }, - { - "name": "Forwarder", - "version": "1.0.0", - "changes": [ - { - "note": "protocol v2 deploy", - "networks": { - "1": "0x7afc2d5107af94c462a194d2c21b5bdd238709d6", - "3": "0x3983e204b12b3c02fb0638caf2cd406a62e0ead3", - "42": "0xd85e2fa7e7e252b27b01bf0d65c946959d2f45b8" - } - } - ] - } -] \ No newline at end of file diff --git a/contracts/extensions/DEPLOYS.json b/contracts/extensions/DEPLOYS.json new file mode 100644 index 000000000..1c181d623 --- /dev/null +++ b/contracts/extensions/DEPLOYS.json @@ -0,0 +1,31 @@ +[ + { + "name": "Forwarder", + "version": "1.1.0", + "changes": [ + { + "note": "Round up when calculating remaining amounts in marketBuy functions", + "pr": 1162, + "networks": { + "1": "0x5468a1dc173652ee28d249c271fa9933144746b1", + "3": "0x2240dab907db71e64d3e0dba4800c83b5c502d4e", + "42": "0x17992e4ffb22730138e4b62aaa6367fa9d3699a6" + } + } + ] + }, + { + "name": "Forwarder", + "version": "1.0.0", + "changes": [ + { + "note": "protocol v2 deploy", + "networks": { + "1": "0x7afc2d5107af94c462a194d2c21b5bdd238709d6", + "3": "0x3983e204b12b3c02fb0638caf2cd406a62e0ead3", + "42": "0xd85e2fa7e7e252b27b01bf0d65c946959d2f45b8" + } + } + ] + } +] \ No newline at end of file -- cgit v1.2.3 From d018f6d9ccb6fd31e9dacb845a68bf6851a4cd4c Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 13 Dec 2018 14:58:48 -0800 Subject: Updated CHANGELOGS --- contracts/extensions/CHANGELOG.json | 11 +++++++++++ contracts/extensions/CHANGELOG.md | 10 ++++++++++ 2 files changed, 21 insertions(+) create mode 100644 contracts/extensions/CHANGELOG.json create mode 100644 contracts/extensions/CHANGELOG.md (limited to 'contracts/extensions') diff --git a/contracts/extensions/CHANGELOG.json b/contracts/extensions/CHANGELOG.json new file mode 100644 index 000000000..19ac770af --- /dev/null +++ b/contracts/extensions/CHANGELOG.json @@ -0,0 +1,11 @@ +[ + { + "timestamp": 1544741676, + "version": "1.0.2", + "changes": [ + { + "note": "Dependencies updated" + } + ] + } +] diff --git a/contracts/extensions/CHANGELOG.md b/contracts/extensions/CHANGELOG.md new file mode 100644 index 000000000..716353d05 --- /dev/null +++ b/contracts/extensions/CHANGELOG.md @@ -0,0 +1,10 @@ + + +CHANGELOG + +## v1.0.2 - _December 13, 2018_ + + * Dependencies updated -- cgit v1.2.3 From 44e516ac65d4923cc83b0112c509317c6a6d87b6 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Thu, 13 Dec 2018 14:58:57 -0800 Subject: Publish - @0x/contracts-examples@1.0.2 - @0x/contracts-extensions@1.0.2 - @0x/contracts-interfaces@1.0.2 - @0x/contracts-libs@1.0.2 - @0x/contracts-multisig@1.0.2 - @0x/contracts-protocol@2.1.59 - @0x/contracts-tokens@1.0.2 - @0x/contracts-utils@1.0.2 --- contracts/extensions/package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/package.json b/contracts/extensions/package.json index 7a200455b..938e1138c 100644 --- a/contracts/extensions/package.json +++ b/contracts/extensions/package.json @@ -1,6 +1,6 @@ { "name": "@0x/contracts-extensions", - "version": "1.0.1", + "version": "1.0.2", "engines": { "node": ">=6.12" }, @@ -71,11 +71,11 @@ }, "dependencies": { "@0x/base-contract": "^3.0.10", - "@0x/contracts-interfaces": "^1.0.1", - "@0x/contracts-libs": "^1.0.1", - "@0x/contracts-protocol": "^2.1.58", - "@0x/contracts-tokens": "^1.0.1", - "@0x/contracts-utils": "^1.0.1", + "@0x/contracts-interfaces": "^1.0.2", + "@0x/contracts-libs": "^1.0.2", + "@0x/contracts-protocol": "^2.1.59", + "@0x/contracts-tokens": "^1.0.2", + "@0x/contracts-utils": "^1.0.2", "@0x/order-utils": "^3.0.7", "@0x/types": "^1.4.1", "@0x/typescript-typings": "^3.0.6", -- cgit v1.2.3 From 91d432aa564d9766d16c615cadcfbe287542af09 Mon Sep 17 00:00:00 2001 From: Leonid Logvinov Date: Fri, 14 Dec 2018 10:14:09 -0800 Subject: Apply prettier --- contracts/extensions/DEPLOYS.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/DEPLOYS.json b/contracts/extensions/DEPLOYS.json index 1c181d623..1a093bf77 100644 --- a/contracts/extensions/DEPLOYS.json +++ b/contracts/extensions/DEPLOYS.json @@ -28,4 +28,4 @@ } ] } -] \ No newline at end of file +] -- cgit v1.2.3 From b4aca370defb9dfe6c01b60d1b522d4a7b731f43 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 28 Nov 2018 18:09:50 -0800 Subject: Writing tests for Compliant Forwarder --- contracts/extensions/test/extensions/forwarder.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'contracts/extensions') diff --git a/contracts/extensions/test/extensions/forwarder.ts b/contracts/extensions/test/extensions/forwarder.ts index 4027f493d..a4afa283e 100644 --- a/contracts/extensions/test/extensions/forwarder.ts +++ b/contracts/extensions/test/extensions/forwarder.ts @@ -61,6 +61,7 @@ describe(ContractName.Forwarder, () => { let wethContract: WETH9Contract; let forwarderWrapper: ForwarderWrapper; let exchangeWrapper: ExchangeWrapper; + let takerPrivateKey: Buffer; let orderWithoutFee: SignedOrder; let orderWithFee: SignedOrder; -- cgit v1.2.3 From 4417c76b130655da3b14209148191d43037e8f8a Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 11 Dec 2018 14:47:52 -0800 Subject: Ported Balance Threshold Filter to new contract directory structure --- contracts/extensions/compiler.json | 2 +- .../BalanceThresholdFilter.sol | 44 + .../MixinBalanceThresholdFilterCore.sol | 319 ++++ .../interfaces/IThresholdAsset.sol | 30 + .../mixins/MBalanceThresholdFilterCore.sol | 81 ++ contracts/extensions/package.json | 2 +- contracts/extensions/src/artifacts/index.ts | 2 + contracts/extensions/src/wrappers/index.ts | 1 + .../test/extensions/balance_threshold_filter.ts | 1530 ++++++++++++++++++++ .../test/utils/balance_threshold_wrapper.ts | 246 ++++ contracts/extensions/tsconfig.json | 2 +- 11 files changed, 2256 insertions(+), 3 deletions(-) create mode 100644 contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol create mode 100644 contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol create mode 100644 contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IThresholdAsset.sol create mode 100644 contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol create mode 100644 contracts/extensions/test/extensions/balance_threshold_filter.ts create mode 100644 contracts/extensions/test/utils/balance_threshold_wrapper.ts (limited to 'contracts/extensions') diff --git a/contracts/extensions/compiler.json b/contracts/extensions/compiler.json index 69d607b3e..e6ed0c215 100644 --- a/contracts/extensions/compiler.json +++ b/contracts/extensions/compiler.json @@ -18,5 +18,5 @@ } } }, - "contracts": ["DutchAuction", "Forwarder"] + "contracts": ["BalanceThresholdFilter", "DutchAuction", "Forwarder"] } diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol b/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol new file mode 100644 index 000000000..a68f6805d --- /dev/null +++ b/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol @@ -0,0 +1,44 @@ +/* + + Copyright 2018 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.4.24; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol"; +import "./interfaces/IThresholdAsset.sol"; +import "./MixinBalanceThresholdFilterCore.sol"; + + +contract BalanceThresholdFilter is MixinBalanceThresholdFilterCore { + + /// @dev Constructs BalanceThresholdFilter. + /// @param exchange Address of 0x exchange. + /// @param thresholdAsset The asset that must be held by makers/takers. + /// @param thresholdBalance The minimum balance of `thresholdAsset` that must be held by makers/takers. + constructor( + address exchange, + address thresholdAsset, + uint256 thresholdBalance + ) + public + { + EXCHANGE = IExchange(exchange); + THRESHOLD_ASSET = IThresholdAsset(thresholdAsset); + THRESHOLD_BALANCE = thresholdBalance; + } +} diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol new file mode 100644 index 000000000..0ad8ccddf --- /dev/null +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -0,0 +1,319 @@ +/* + + Copyright 2018 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.4.24; +pragma experimental ABIEncoderV2; + +import "./mixins/MBalanceThresholdFilterCore.sol"; + + +contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { + + /// @dev Executes an Exchange transaction iff the maker and taker meet + /// the hold at least `BALANCE_THRESHOLD` of the asset `THRESHOLD_ASSET` OR + /// the exchange function is a cancellation. + /// Supported Exchange functions: + /// - batchFillOrders + /// - batchFillOrdersNoThrow + /// - batchFillOrKillOrders + /// - fillOrder + /// - fillOrderNoThrow + /// - fillOrKillOrder + /// - marketBuyOrders + /// - marketBuyOrdersNoThrow + /// - marketSellOrders + /// - marketSellOrdersNoThrow + /// - matchOrders + /// - cancelOrder + /// - batchCancelOrders + /// - cancelOrdersUpTo + /// Trying to call any other exchange function will throw. + /// @param salt Arbitrary number to ensure uniqueness of transaction hash. + /// @param signerAddress Address of transaction signer. + /// @param signedExchangeTransaction AbiV2 encoded calldata. + /// @param signature Proof of signer transaction by signer. + function executeTransaction( + uint256 salt, + address signerAddress, + bytes signedExchangeTransaction, + bytes signature + ) + external + { + // Validate addresses. + validateBalanceThresholdsOrRevert(); + + // All addresses are valid. Execute fillOrder. + EXCHANGE.executeTransaction( + salt, + signerAddress, + signedExchangeTransaction, + signature + ); + } + + /// @dev Validates addresses meet the balance threshold specified by `BALANCE_THRESHOLD` + /// for the asset `THRESHOLD_ASSET`. If one address does not meet the thresold + /// then this function will revert. Which addresses are validated depends on + /// which Exchange function is to be called (defined by `signedExchangeTransaction` above). + /// No parameters are taken as this function reads arguments directly from calldata, to save gas. + /// If all addresses are valid then this function emits a ValidatedAddresses event, listing all + /// of the addresses whose balance thresholds it checked. + function validateBalanceThresholdsOrRevert() + internal + { + // Addresses that are validated below. + address[] memory validatedAddresses; + + ///// Do not add variables after this point. ///// + ///// The assembly block may overwrite their values. ///// + + // Validate addresses + assembly { + /// @dev Emulates the `calldataload` opcode on the embedded Exchange calldata, + /// which is accessed through `signedExchangeTransaction`. + /// @param offset - Offset into the Exchange calldata. + /// @return value - Corresponding 32 byte value stored at `offset`. + function exchangeCalldataload(offset) -> value { + // Pointer to exchange transaction + // 0x04 for calldata selector + // 0x40 to access `signedExchangeTransaction`, which is the third parameter + let exchangeTxPtr := calldataload(0x44) + + // Offset into Exchange calldata + // We compute this by adding 0x24 to the `exchangeTxPtr` computed above. + // 0x04 for calldata selector + // 0x20 for length field of `signedExchangeTransaction` + let exchangeCalldataOffset := add(exchangeTxPtr, add(0x24, offset)) + value := calldataload(exchangeCalldataOffset) + } + + /// @dev Convenience function that skips the 4 byte selector when loading + /// from the embedded Exchange calldata. + /// @param offset - Offset into the Exchange calldata (minus the 4 byte selector) + /// @return value - Corresponding 32 byte value stored at `offset` + 4. + function loadExchangeData(offset) -> value { + value := exchangeCalldataload(add(offset, 0x4)) + } + + /// @dev A running list is maintained of addresses to validate. + /// This function records an address in this array. + /// @param addressToValidate - Address to record for validation. + function recordAddressToValidate(addressToValidate) { + // Compute `addressesToValidate` memory offset + let addressesToValidate_ := mload(0x40) + let nAddressesToValidate_ := mload(addressesToValidate_) + + // Increment length + nAddressesToValidate_ := add(mload(addressesToValidate_), 0x01) + mstore(addressesToValidate_, nAddressesToValidate_) + + // Append address to validate + let offset := mul(nAddressesToValidate_, 0x20) + mstore(add(addressesToValidate_, offset), addressToValidate) + } + + /// @dev Extracts the maker address from an order stored in the Exchange calldata + /// (which is embedded in `signedExchangeTransaction`), and records it in + /// the running list of addresses to validate. + /// @param orderParamIndex - Index of the order in the Exchange function's signature + function recordMakerAddressFromOrder(orderParamIndex) { + let orderPtr := loadExchangeData(mul(orderParamIndex, 0x20)) + let makerAddress := loadExchangeData(orderPtr) + recordAddressToValidate(makerAddress) + } + + /// @dev Extracts the maker addresses from an array of orders stored in the Exchange calldata + /// (which is embedded in `signedExchangeTransaction`), and records them in + /// the running list of addresses to validate. + /// @param orderArrayParamIndex - Index of the order array in the Exchange function's signature + function recordMakerAddressesFromOrderArray(orderArrayParamIndex) { + let orderArrayPtr := loadExchangeData(mul(orderArrayParamIndex, 0x20)) + let orderArrayLength := loadExchangeData(orderArrayPtr) + let orderArrayElementPtr := add(orderArrayPtr, 0x20) + let orderArrayElementEndPtr := add(orderArrayElementPtr, mul(orderArrayLength, 0x20)) + for {let orderPtrOffset := orderArrayElementPtr} lt(orderPtrOffset, orderArrayElementEndPtr) {orderPtrOffset := add(orderPtrOffset, 0x20)} { + let orderPtr := loadExchangeData(orderPtrOffset) + let makerAddress := loadExchangeData(add(orderPtr, orderArrayElementPtr)) + recordAddressToValidate(makerAddress) + } + } + + /// @dev Records address of signer in the running list of addresses to validate. + /// @note: We cannot access `signerAddress` directly from within the asm function, + /// so it is loaded from the calldata. + function recordSignerAddress() { + // Load the signer address from calldata + // 0x04 for selector + // 0x20 to access `signerAddress`, which is the second parameter. + let signerAddress_ := calldataload(0x24) + recordAddressToValidate(signerAddress_) + } + + /// @dev Records addresses to be validated when Exchange transaction is a batch fill variant. + /// This is one of: batchFillOrders, batchFillOrKillOrders, batchFillNoThrow + /// Reference signature: (Order[],uint256[],bytes[]) + function recordAddressesForBatchFillVariant() { + // Record maker addresses from order array (parameter index 0) + // The signer is the taker for these orders and must also be validated. + recordMakerAddressesFromOrderArray(0) + recordSignerAddress() + } + + /// @dev Records addresses to be validated when Exchange transaction is a fill order variant. + /// This is one of: fillOrder, fillOrKillOrder, fillOrderNoThrow + /// Reference signature: (Order,uint256,bytes) + function recordAddressesForFillOrderVariant() { + // Record maker address from the order (param index 0) + // The signer is the taker for this order and must also be validated. + recordMakerAddressFromOrder(0) + recordSignerAddress() + } + + /// @dev Records addresses to be validated when Exchange transaction is a market fill variant. + /// This is one of: marketBuyOrders, marketBuyOrdersNoThrow, marketSellOrders, marketSellOrdersNoThrow + /// Reference signature: (Order[],uint256,bytes[]) + function recordAddressesForMarketFillVariant() { + // Record maker addresses from order array (parameter index 0) + // The signer is the taker for these orders and must also be validated. + recordMakerAddressesFromOrderArray(0) + recordSignerAddress() + } + + /// @dev Records addresses to be validated when Exchange transaction is matchOrders. + /// Reference signature: matchOrders(Order,Order) + function recordAddressesForMatchOrders() { + // Record maker address from both orders (param indices 0 & 1). + // The signer is the taker and must also be validated. + recordMakerAddressFromOrder(0) + recordMakerAddressFromOrder(1) + recordSignerAddress() + } + + ///// Record Addresses to Validate ///// + + // Addresses needing validation depends on which Exchange function is being called. + // Step 1/2 Read the exchange function selector. + let exchangeFunctionSelector := and( + exchangeCalldataload(0x0), + 0xffffffff00000000000000000000000000000000000000000000000000000000 + ) + + // Step 2/2 Extract addresses to validate based on this selector. + // See ../../utils/ExchangeSelectors/ExchangeSelectors.sol for selectors + switch exchangeFunctionSelector + case 0x297bb70b00000000000000000000000000000000000000000000000000000000 { recordAddressesForBatchFillVariant() } // batchFillOrders + case 0x50dde19000000000000000000000000000000000000000000000000000000000 { recordAddressesForBatchFillVariant() } // batchFillOrdersNoThrow + case 0x4d0ae54600000000000000000000000000000000000000000000000000000000 { recordAddressesForBatchFillVariant() } // batchFillOrKillOrders + case 0xb4be83d500000000000000000000000000000000000000000000000000000000 { recordAddressesForFillOrderVariant() } // fillOrder + case 0x3e228bae00000000000000000000000000000000000000000000000000000000 { recordAddressesForFillOrderVariant() } // fillOrderNoThrow + case 0x64a3bc1500000000000000000000000000000000000000000000000000000000 { recordAddressesForFillOrderVariant() } // fillOrKillOrder + case 0xe5fa431b00000000000000000000000000000000000000000000000000000000 { recordAddressesForMarketFillVariant() } // marketBuyOrders + case 0xa3e2038000000000000000000000000000000000000000000000000000000000 { recordAddressesForMarketFillVariant() } // marketBuyOrdersNoThrow + case 0x7e1d980800000000000000000000000000000000000000000000000000000000 { recordAddressesForMarketFillVariant() } // marketSellOrders + case 0xdd1c7d1800000000000000000000000000000000000000000000000000000000 { recordAddressesForMarketFillVariant() } // marketSellOrdersNoThrow + case 0x3c28d86100000000000000000000000000000000000000000000000000000000 { recordAddressesForMatchOrders() } // matchOrders + case 0xd46b02c300000000000000000000000000000000000000000000000000000000 {} // cancelOrder + case 0x4ac1478200000000000000000000000000000000000000000000000000000000 {} // batchCancelOrders + case 0x4f9559b100000000000000000000000000000000000000000000000000000000 {} // cancelOrdersUpTo + default { + // Revert with `Error("INVALID_OR_BLOCKED_EXCHANGE_SELECTOR")` + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000) + mstore(0x40, 0x00000024494e56414c49445f4f525f424c4f434b45445f45584348414e47455f) + mstore(0x60, 0x53454c4543544f52000000000000000000000000000000000000000000000000) + mstore(0x80, 0x00000000) + // Revert length calculation: + // 4 -- error selector + // 32 -- offset to string + // 32 -- string length field + // 64 -- strlen(INVALID_OR_BLOCKED_EXCHANGE_SELECTOR) rounded up to nearest 32-byte word. + revert(0, 132) + } + + ///// Validate Recorded Addresses ///// + + // Load from memory the addresses to validate + let addressesToValidate := mload(0x40) + let addressesToValidateLength := mload(addressesToValidate) + let addressesToValidateElementPtr := add(addressesToValidate, 0x20) + let addressesToValidateElementEndPtr := add(addressesToValidateElementPtr, mul(addressesToValidateLength, 0x20)) + + // Set free memory pointer to after `addressesToValidate` array. + // This is to avoid corruption when making calls in the loop below. + let freeMemPtr := addressesToValidateElementEndPtr + mstore(0x40, freeMemPtr) + + // Validate addresses + let thresholdAssetAddress := sload(THRESHOLD_ASSET_slot) + let thresholdBalance := sload(THRESHOLD_BALANCE_slot) + for {let addressToValidate := addressesToValidateElementPtr} lt(addressToValidate, addressesToValidateElementEndPtr) {addressToValidate := add(addressToValidate, 0x20)} { + // Construct calldata for `THRESHOLD_ASSET.balanceOf` + mstore(freeMemPtr, 0x70a0823100000000000000000000000000000000000000000000000000000000) + mstore(add(freeMemPtr, 0x04), mload(addressToValidate)) + + // call `THRESHOLD_ASSET.balanceOf` + let success := call( + gas, // forward all gas + thresholdAssetAddress, // call address of asset proxy + 0, // don't send any ETH + freeMemPtr, // pointer to start of input + 0x24, // length of input (one padded address) + freeMemPtr, // write output to next free memory offset + 0x20 // reserve space for return balance (0x20 bytes) + ) + if eq(success, 0) { + // @TODO Revert with `Error("BALANCE_QUERY_FAILED")` + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000) + mstore(0x40, 0x0000001442414c414e43455f51554552595f4641494c45440000000000000000) + mstore(0x60, 0x00000000) + // Revert length calculation: + // 4 -- error selector + // 32 -- offset to string + // 32 -- string length field + // 32 -- strlen(BALANCE_QUERY_FAILED) rounded up to nearest 32-byte word. + revert(0, 100) + } + + // Revert if balance not held + let addressBalance := mload(freeMemPtr) + if lt(addressBalance, thresholdBalance) { + // Revert with `Error("AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD")` + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000) + mstore(0x40, 0x0000003441545f4c454153545f4f4e455f414444524553535f444f45535f4e4f) + mstore(0x60, 0x545f4d4545545f42414c414e43455f5448524553484f4c440000000000000000) + mstore(0x80, 0x00000000) + // Revert length calculation: + // 4 -- error selector + // 32 -- offset to string + // 32 -- string length field + // 64 -- strlen(AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD) rounded up to nearest 32-byte word. + revert(0, 132) + } + } + + // Record validated addresses + validatedAddresses := addressesToValidate + } + + ///// If we hit this point then all addresses are valid ///// + emit ValidatedAddresses(validatedAddresses); + } +} \ No newline at end of file diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IThresholdAsset.sol b/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IThresholdAsset.sol new file mode 100644 index 000000000..61acaba0a --- /dev/null +++ b/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IThresholdAsset.sol @@ -0,0 +1,30 @@ +/* + + Copyright 2018 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.4.24; + +contract IThresholdAsset { + + /// @param _owner The address from which the balance will be retrieved + /// @return Balance of owner + function balanceOf(address _owner) + external + view + returns (uint256); + +} \ No newline at end of file diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol new file mode 100644 index 000000000..ff0042f58 --- /dev/null +++ b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol @@ -0,0 +1,81 @@ +/* + + Copyright 2018 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.4.24; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol"; +import "../interfaces/IThresholdAsset.sol"; + + +contract MBalanceThresholdFilterCore { + + // Points to 0x exchange contract + IExchange internal EXCHANGE; + + // The asset that must be held by makers/takers + IThresholdAsset internal THRESHOLD_ASSET; + + // The minimum balance of `THRESHOLD_ASSET` that must be held by makers/takers + uint256 internal THRESHOLD_BALANCE; + + // Addresses that hold at least `THRESHOLD_BALANCE` of `THRESHOLD_ASSET` + event ValidatedAddresses ( + address[] addresses + ); + + /// @dev Executes an Exchange transaction iff the maker and taker meet + /// the hold at least `BALANCE_THRESHOLD` of the asset `THRESHOLD_ASSET` OR + /// the exchange function is a cancellation. + /// Supported Exchange functions: + /// - batchFillOrders + /// - batchFillOrdersNoThrow + /// - batchFillOrKillOrders + /// - fillOrder + /// - fillOrderNoThrow + /// - fillOrKillOrder + /// - marketBuyOrders + /// - marketBuyOrdersNoThrow + /// - marketSellOrders + /// - marketSellOrdersNoThrow + /// - matchOrders + /// - cancelOrder + /// - batchCancelOrders + /// - cancelOrdersUpTo + /// Trying to call any other exchange function will throw. + /// @param salt Arbitrary number to ensure uniqueness of transaction hash. + /// @param signerAddress Address of transaction signer. + /// @param signedExchangeTransaction AbiV2 encoded calldata. + /// @param signature Proof of signer transaction by signer. + function executeTransaction( + uint256 salt, + address signerAddress, + bytes signedExchangeTransaction, + bytes signature + ) + external; + + /// @dev Validates addresses meet the balance threshold specified by `BALANCE_THRESHOLD` + /// for the asset `THRESHOLD_ASSET`. If one address does not meet the thresold + /// then this function will revert. Which addresses are validated depends on + /// which Exchange function is to be called (defined by `signedExchangeTransaction` above). + /// No parameters are taken as this function reads arguments directly from calldata, to save gas. + /// If all addresses are valid then this function emits a ValidatedAddresses event, listing all + /// of the addresses whose balance thresholds it checked. + function validateBalanceThresholdsOrRevert() internal; +} \ No newline at end of file diff --git a/contracts/extensions/package.json b/contracts/extensions/package.json index 938e1138c..2d9ed4dcd 100644 --- a/contracts/extensions/package.json +++ b/contracts/extensions/package.json @@ -31,7 +31,7 @@ "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol" }, "config": { - "abis": "generated-artifacts/@(DutchAuction|Forwarder).json" + "abis": "generated-artifacts/@(BalanceThresholdFilter|DutchAuction|Forwarder).json" }, "repository": { "type": "git", diff --git a/contracts/extensions/src/artifacts/index.ts b/contracts/extensions/src/artifacts/index.ts index 7588178f0..ebf0b8050 100644 --- a/contracts/extensions/src/artifacts/index.ts +++ b/contracts/extensions/src/artifacts/index.ts @@ -1,9 +1,11 @@ import { ContractArtifact } from 'ethereum-types'; +import * as BalanceThresholdFilter from '../../generated-artifacts/BalanceThresholdFilter.json'; import * as DutchAuction from '../../generated-artifacts/DutchAuction.json'; import * as Forwarder from '../../generated-artifacts/Forwarder.json'; export const artifacts = { + BalanceThresholdFilter: BalanceThresholdFilter as ContractArtifact, DutchAuction: DutchAuction as ContractArtifact, Forwarder: Forwarder as ContractArtifact, }; diff --git a/contracts/extensions/src/wrappers/index.ts b/contracts/extensions/src/wrappers/index.ts index 90880e37f..8a8122caa 100644 --- a/contracts/extensions/src/wrappers/index.ts +++ b/contracts/extensions/src/wrappers/index.ts @@ -1,2 +1,3 @@ +export * from '../../generated-wrappers/balance_threshold_filter'; export * from '../../generated-wrappers/dutch_auction'; export * from '../../generated-wrappers/forwarder'; diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts new file mode 100644 index 000000000..34339564c --- /dev/null +++ b/contracts/extensions/test/extensions/balance_threshold_filter.ts @@ -0,0 +1,1530 @@ +import { BlockchainLifecycle } from '@0x/dev-utils'; +import { assetDataUtils } from '@0x/order-utils'; +import { RevertReason, SignedOrder, Order } from '@0x/types'; +import { BigNumber } from '@0x/utils'; +import { Web3Wrapper } from '@0x/web3-wrapper'; +import * as chai from 'chai'; +import * as ethUtil from 'ethereumjs-util'; +import * as _ from 'lodash'; +import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; + +import { + artifacts as protocolArtifacts, + ERC20Wrapper, + ERC721Wrapper, + ExchangeContract, + ExchangeWrapper, + TestExchangeInternalsContract, +} from '@0x/contracts-protocol'; +import { + chaiSetup, + constants, + ContractName, + ERC20BalancesByOwner, + expectTransactionFailedAsync, + expectTransactionFailedWithoutReasonAsync, + getLatestBlockTimestampAsync, + LogDecoder, + OrderFactory, + OrderStatus, + orderUtils, + provider, + SignedTransaction, + txDefaults, + TransactionFactory, + web3Wrapper, +} from '@0x/contracts-test-utils'; +import { + artifacts as tokensArtifacts, + DummyERC20TokenContract, + DummyERC721TokenContract, + WETH9Contract, +} from '@0x/contracts-tokens'; + +import { artifacts } from '../../src/artifacts'; +import { BalanceThresholdFilterContract } from '../../generated-wrappers/balance_threshold_filter'; +import { BalanceThresholdWrapper } from '../utils/balance_threshold_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); +const DECIMALS_DEFAULT = 18; + +interface ValidatedAddressesLog { + args: {addresses: string[]} +} + +describe.only(ContractName.BalanceThresholdFilter, () => { + let compliantMakerAddress: string; + let compliantMakerAddress2: string; + let owner: string; + let compliantTakerAddress: string; + let feeRecipientAddress: string; + let nonCompliantAddress: string; + let defaultMakerAssetAddress: string; + let defaultTakerAssetAddress: string; + let zrxAssetData: string; + let zrxToken: DummyERC20TokenContract; + let exchangeInstance: ExchangeContract; + let exchangeWrapper: ExchangeWrapper; + + let orderFactory: OrderFactory; + let orderFactory2: OrderFactory; + let nonCompliantOrderFactory: OrderFactory; + let erc20Wrapper: ERC20Wrapper; + let erc20Balances: ERC20BalancesByOwner; + let erc20TakerBalanceThresholdWrapper: BalanceThresholdWrapper; + let erc721TakerBalanceThresholdWrapper: BalanceThresholdWrapper; + let erc721MakerBalanceThresholdWrapper: BalanceThresholdWrapper; + let erc721NonCompliantBalanceThresholdWrapper: BalanceThresholdWrapper; + + let takerTransactionFactory: TransactionFactory; + let makerTransactionFactory: TransactionFactory; + let compliantSignedOrder: SignedOrder; + let compliantSignedOrder2: SignedOrder; + let compliantSignedFillOrderTx: SignedTransaction; + + let logDecoder: LogDecoder; + let exchangeInternals: TestExchangeInternalsContract; + + let defaultOrderParams: Partial; + + const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT); + const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT); + const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT); + + let erc721CompliantForwarderInstance: BalanceThresholdFilterContract; + let erc20CompliantForwarderInstance: BalanceThresholdFilterContract; + + const assertValidatedAddressesLog = async (txReceipt: TransactionReceiptWithDecodedLogs, expectedValidatedAddresses: string[]) => { + expect(txReceipt.logs.length).to.be.gte(1); + const validatedAddressesLog = (txReceipt.logs[0] as any) as ValidatedAddressesLog; + const validatedAddresses = validatedAddressesLog.args.addresses; + // @HACK-hysz: Nested addresses are not translated to lower-case but this will change once + // the new ABI Encoder/Decoder is used by the contract templates. + let validatedAddressesNormalized: string[] = []; + _.each(validatedAddresses, (address) => { + const normalizedAddress = _.toLower(address); + validatedAddressesNormalized.push(normalizedAddress); + }); + expect(validatedAddressesNormalized).to.be.deep.equal(expectedValidatedAddresses); + }; + + before(async () => { + // Create accounts + await blockchainLifecycle.startAsync(); + const accounts = await web3Wrapper.getAvailableAddressesAsync(); + const usedAddresses = ([ + owner, + compliantMakerAddress, + compliantMakerAddress2, + compliantTakerAddress, + feeRecipientAddress, + nonCompliantAddress, + ] = accounts); + // Create wrappers + erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); + let compliantAddresses = _.cloneDeepWith(usedAddresses); + _.remove(compliantAddresses, (address: string) => { + return address === nonCompliantAddress; + }); + const erc721Wrapper = new ERC721Wrapper(provider, compliantAddresses, owner); + // Deploy ERC20 tokens + const numDummyErc20ToDeploy = 4; + let erc20TokenA: DummyERC20TokenContract; + let erc20TokenB: DummyERC20TokenContract; + let erc20BalanceThresholdAsset: DummyERC20TokenContract; + [erc20TokenA, erc20TokenB, zrxToken, erc20BalanceThresholdAsset] = await erc20Wrapper.deployDummyTokensAsync( + numDummyErc20ToDeploy, + constants.DUMMY_TOKEN_DECIMALS, + ); + defaultMakerAssetAddress = erc20TokenA.address; + defaultTakerAssetAddress = erc20TokenB.address; + zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); + // Create proxies + const erc20Proxy = await erc20Wrapper.deployProxyAsync(); + await erc20Wrapper.setBalancesAndAllowancesAsync(); + // Deploy Exchange congtract + exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync( + protocolArtifacts.Exchange, + provider, + txDefaults, + zrxAssetData, + ); + exchangeWrapper = new ExchangeWrapper(exchangeInstance, provider); + // Register proxies + await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner); + await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, { + from: owner, + }); + // Deploy Compliant Forwarder + const erc721alanceThreshold = new BigNumber(1); + await erc721Wrapper.deployProxyAsync(); + const [erc721BalanceThresholdAsset] = await erc721Wrapper.deployDummyTokensAsync(); + await erc721Wrapper.setBalancesAndAllowancesAsync(); + erc721CompliantForwarderInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync( + artifacts.BalanceThresholdFilter, + provider, + txDefaults, + exchangeInstance.address, + erc721BalanceThresholdAsset.address, + erc721alanceThreshold + ); + const erc20BalanceThreshold = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 10); + erc20CompliantForwarderInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync( + artifacts.BalanceThresholdFilter, + provider, + txDefaults, + exchangeInstance.address, + erc20BalanceThresholdAsset.address, + erc20BalanceThreshold + ); + + // Default order parameters + defaultOrderParams = { + exchangeAddress: exchangeInstance.address, + feeRecipientAddress, + makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), + takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), + makerAssetAmount, + takerAssetAmount, + makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS_DEFAULT), + takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(150), DECIMALS_DEFAULT), + senderAddress: erc721CompliantForwarderInstance.address, + }; + const defaultOrderParams1 = { + makerAddress: compliantMakerAddress, + ... + defaultOrderParams, + } + const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantMakerAddress)]; + takerTransactionFactory = new TransactionFactory(makerPrivateKey, exchangeInstance.address); + orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams1); + const defaultOrderParams2 = { + makerAddress: compliantMakerAddress2, + ... + defaultOrderParams, + } + const secondMakerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantMakerAddress2)]; + orderFactory2 = new OrderFactory(secondMakerPrivateKey, defaultOrderParams2); + + const nonCompliantPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(nonCompliantAddress)]; + const defaultNonCompliantOrderParams = { + makerAddress: nonCompliantAddress, + ... + defaultOrderParams, + }; + nonCompliantOrderFactory = new OrderFactory(nonCompliantPrivateKey, defaultNonCompliantOrderParams); + // Create Valid/Invalid orders + const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantTakerAddress)]; + takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchangeInstance.address); + compliantSignedOrder = await orderFactory.newSignedOrderAsync({ + senderAddress: erc721CompliantForwarderInstance.address, + }); + const compliantSignedOrderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress( + compliantSignedOrder, + ); + const compliantSignedOrderWithoutExchangeAddressData = exchangeInstance.fillOrder.getABIEncodedTransactionData( + compliantSignedOrderWithoutExchangeAddress, + takerAssetFillAmount, + compliantSignedOrder.signature, + ); + compliantSignedFillOrderTx = takerTransactionFactory.newSignedTransaction( + compliantSignedOrderWithoutExchangeAddressData, + ); + + logDecoder = new LogDecoder(web3Wrapper, {... artifacts, ... protocolArtifacts, ... tokensArtifacts}); + erc20TakerBalanceThresholdWrapper = new BalanceThresholdWrapper(erc20CompliantForwarderInstance, exchangeInstance, new TransactionFactory(takerPrivateKey, exchangeInstance.address), provider); + erc721TakerBalanceThresholdWrapper = new BalanceThresholdWrapper(erc721CompliantForwarderInstance, exchangeInstance, new TransactionFactory(takerPrivateKey, exchangeInstance.address), provider); + erc721MakerBalanceThresholdWrapper = new BalanceThresholdWrapper(erc721CompliantForwarderInstance, exchangeInstance, new TransactionFactory(makerPrivateKey, exchangeInstance.address), provider); + erc721NonCompliantBalanceThresholdWrapper = new BalanceThresholdWrapper(erc721CompliantForwarderInstance, exchangeInstance, new TransactionFactory(nonCompliantPrivateKey, exchangeInstance.address), provider); + + // Instantiate internal exchange contract + exchangeInternals = await TestExchangeInternalsContract.deployFrom0xArtifactAsync( + protocolArtifacts.TestExchangeInternals, + provider, + txDefaults, + ); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + + describe('General Sanity Checks', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both maker/taker when both maker and taker exceed the balance threshold of an ERC20 token', async () => { + const compliantSignedOrderERC20Sender = await orderFactory.newSignedOrderAsync({ + ... + defaultOrderParams, + makerAddress: compliantMakerAddress, + senderAddress: erc20TakerBalanceThresholdWrapper.getBalanceThresholdAddress(), + }); + // Execute a valid fill + const txReceipt = await erc20TakerBalanceThresholdWrapper.fillOrderAsync(compliantSignedOrderERC20Sender, compliantTakerAddress, {takerAssetFillAmount}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const makerAssetFillAmount = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid = compliantSignedOrder.makerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + ); + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)), + ); + }); + it('should revert if the signed transaction is not intended for supported', async () => { + // Create signed order without the fillOrder function selector + const txDataBuf = ethUtil.toBuffer(compliantSignedFillOrderTx.data); + const selectorLengthInBytes = 4; + const txDataBufMinusSelector = txDataBuf.slice(selectorLengthInBytes); + const badSelector = '0x00000000'; + const badSelectorBuf = ethUtil.toBuffer(badSelector); + const txDataBufWithBadSelector = Buffer.concat([badSelectorBuf, txDataBufMinusSelector]); + const txDataBufWithBadSelectorHex = ethUtil.bufferToHex(txDataBufWithBadSelector); + // Call compliant forwarder + return expectTransactionFailedWithoutReasonAsync(erc721CompliantForwarderInstance.executeTransaction.sendTransactionAsync( + compliantSignedFillOrderTx.salt, + compliantSignedFillOrderTx.signerAddress, + txDataBufWithBadSelectorHex, + compliantSignedFillOrderTx.signature, + )); + }); + it('should revert if senderAddress is not set to the compliant forwarding contract', async () => { + // Create signed order with incorrect senderAddress + const notBalanceThresholdFilterAddress = zrxToken.address; + const signedOrderWithBadSenderAddress = await orderFactory.newSignedOrderAsync({ + senderAddress: notBalanceThresholdFilterAddress, + }); + const signedOrderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress( + signedOrderWithBadSenderAddress, + ); + const signedOrderWithoutExchangeAddressData = exchangeInstance.fillOrder.getABIEncodedTransactionData( + signedOrderWithoutExchangeAddress, + takerAssetFillAmount, + compliantSignedOrder.signature, + ); + const signedFillOrderTx = takerTransactionFactory.newSignedTransaction( + signedOrderWithoutExchangeAddressData, + ); + // Call compliant forwarder + return expectTransactionFailedWithoutReasonAsync(erc721CompliantForwarderInstance.executeTransaction.sendTransactionAsync( + signedFillOrderTx.salt, + signedFillOrderTx.signerAddress, + signedFillOrderTx.data, + signedFillOrderTx.signature, + )); + }); + // @TODO - greater than 1 balance + }); + + describe('batchFillOrders', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both makers/taker when both maker and taker meet the balance threshold', async () => { + // Execute a valid fill + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync(orders, compliantTakerAddress, {takerAssetFillAmounts}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); + const makerAssetFillAmount = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid = compliantSignedOrder.makerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount) + .times(2); + // Maker #1 + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + ); + // Maker #2 + expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), + ); + // Taker + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + ); + + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + // Fee recipient + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.times(2).add(takerFeePaid)), + ); + }); + it('should revert if one maker does not meet the balance threshold', async () => { + // Create order set with one non-compliant maker address + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + makerAddress: nonCompliantAddress + }); + const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync( + orders, + compliantTakerAddress, + {takerAssetFillAmounts} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.batchFillOrdersAsync( + orders, + nonCompliantAddress, + {takerAssetFillAmounts} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('batchFillOrdersNoThrow', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both makers/taker when both maker and taker meet the balance threshold', async () => { + // Execute a valid fill + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, compliantTakerAddress, {takerAssetFillAmounts}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); + const makerAssetFillAmount = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid = compliantSignedOrder.makerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount) + .times(2); + // Maker #1 + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + ); + // Maker #2 + expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), + ); + // Taker + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + ); + + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + // Fee recipient + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.times(2).add(takerFeePaid)), + ); + }); + it('should revert if one maker does not meet the balance threshold', async () => { + // Create order set with one non-compliant maker address + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + makerAddress: nonCompliantAddress + }); + const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync( + orders, + compliantTakerAddress, + {takerAssetFillAmounts} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.batchFillOrdersNoThrowAsync( + orders, + nonCompliantAddress, + {takerAssetFillAmounts} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('batchFillOrKillOrders', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { + // Execute a valid fill + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, compliantTakerAddress, {takerAssetFillAmounts}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); + const makerAssetFillAmount = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid = compliantSignedOrder.makerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount) + .times(2); + // Maker #1 + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + ); + // Maker #2 + expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), + ); + // Taker + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + ); + + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + // Fee recipient + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.times(2).add(takerFeePaid)), + ); + }); + it('should revert if one maker does not meet the balance threshold', async () => { + // Create order set with one non-compliant maker address + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + makerAddress: nonCompliantAddress + }); + const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync( + orders, + compliantTakerAddress, + {takerAssetFillAmounts} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.batchFillOrKillOrdersAsync( + orders, + nonCompliantAddress, + {takerAssetFillAmounts} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if one takerAssetFillAmount is not fully filled', async () => { + const tooBigTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.times(2); + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const takerAssetFillAmounts = [takerAssetFillAmount, tooBigTakerAssetFillAmount]; + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync( + orders, + compliantTakerAddress, + {takerAssetFillAmounts} + ), + RevertReason.FailedExecution + ); + }); + }); + + describe('fillOrder', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { + // Execute a valid fill + const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderAsync(compliantSignedOrder, compliantTakerAddress, {takerAssetFillAmount}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const makerAssetFillAmount = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid = compliantSignedOrder.makerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + ); + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)), + ); + }); + it('should revert if maker does not meet the balance threshold', async () => { + // Create signed order with non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + senderAddress: erc721CompliantForwarderInstance.address, + makerAddress: nonCompliantAddress + }); + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.fillOrderAsync( + signedOrderWithBadMakerAddress, + compliantTakerAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.fillOrderAsync( + compliantSignedOrder, + nonCompliantAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('fillOrderNoThrow', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { + // Execute a valid fill + const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync(compliantSignedOrder, compliantTakerAddress, {takerAssetFillAmount}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const makerAssetFillAmount = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid = compliantSignedOrder.makerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + ); + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)), + ); + }); + it('should revert if maker does not meet the balance threshold', async () => { + // Create signed order with non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + senderAddress: erc721CompliantForwarderInstance.address, + makerAddress: nonCompliantAddress + }); + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync( + signedOrderWithBadMakerAddress, + compliantTakerAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.fillOrderNoThrowAsync( + compliantSignedOrder, + nonCompliantAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('fillOrKillOrder', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { + // Execute a valid fill + const takerAssetFillAmount_ = compliantSignedOrder.takerAssetAmount; + const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync(compliantSignedOrder, compliantTakerAddress, {takerAssetFillAmount: takerAssetFillAmount_}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const makerAssetFillAmount = takerAssetFillAmount_ + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid = compliantSignedOrder.makerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee + .times(makerAssetFillAmount) + .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount_), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + ); + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount_), + ); + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)), + ); + }); + it('should revert if maker does not meet the balance threshold', async () => { + // Create signed order with non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + senderAddress: erc721CompliantForwarderInstance.address, + makerAddress: nonCompliantAddress + }); + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync( + signedOrderWithBadMakerAddress, + compliantTakerAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.fillOrKillOrderAsync( + compliantSignedOrder, + nonCompliantAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if takerAssetFillAmount is not fully filled', async () => { + const tooBigTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.times(2); + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync( + compliantSignedOrder, + compliantTakerAddress, + {takerAssetFillAmount: tooBigTakerAssetFillAmount} + ), + RevertReason.FailedExecution + ); + }); + }); + + describe('marketSellOrders', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { + // Execute a valid fill + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync(orders, compliantTakerAddress, {takerAssetFillAmount: cumulativeTakerAssetFillAmount}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const makerAssetFillAmount2 = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid2 = compliantSignedOrder2.makerFee + .times(makerAssetFillAmount2) + .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); + const takerFeePaid2 = compliantSignedOrder2.takerFee + .times(makerAssetFillAmount2) + .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); + const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); + // Maker #1 + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(compliantSignedOrder.makerAssetAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(compliantSignedOrder.takerAssetAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), + ); + // Maker #2 + expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), + ); + expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), + ); + // Taker + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + // Fee recipient + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(compliantSignedOrder.makerFee).add(makerFeePaid2).add(takerFeePaid), + ); + }); + it('should revert if one maker does not meet the balance threshold', async () => { + // Create order set with one non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + makerAddress: nonCompliantAddress + }); + const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync( + orders, + compliantTakerAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + const orders = [compliantSignedOrder, compliantSignedOrder2]; + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.marketSellOrdersAsync( + orders, + nonCompliantAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('marketSellOrdersNoThrow', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { + // Execute a valid fill + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, compliantTakerAddress, {takerAssetFillAmount: cumulativeTakerAssetFillAmount}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const makerAssetFillAmount2 = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const makerFeePaid2 = compliantSignedOrder2.makerFee + .times(makerAssetFillAmount2) + .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); + const takerFeePaid2 = compliantSignedOrder2.takerFee + .times(makerAssetFillAmount2) + .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); + const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); + // Maker #1 + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(compliantSignedOrder.makerAssetAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(compliantSignedOrder.takerAssetAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), + ); + // Maker #2 + expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), + ); + expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), + ); + // Taker + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + // Fee recipient + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(compliantSignedOrder.makerFee).add(makerFeePaid2).add(takerFeePaid), + ); + }); + it('should revert if one maker does not meet the balance threshold', async () => { + // Create order set with one non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + makerAddress: nonCompliantAddress + }); + const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync( + orders, + compliantTakerAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + const orders = [compliantSignedOrder, compliantSignedOrder2]; + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.marketSellOrdersNoThrowAsync( + orders, + nonCompliantAddress, + {takerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('marketBuyOrders', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { + // Execute a valid fill + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); + const makerAssetFillAmount2 = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync(orders, compliantTakerAddress, {makerAssetFillAmount: cumulativeMakerAssetFillAmount}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const makerFeePaid2 = compliantSignedOrder2.makerFee + .times(makerAssetFillAmount2) + .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); + const takerFeePaid2 = compliantSignedOrder2.takerFee + .times(makerAssetFillAmount2) + .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); + // Maker #1 + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(compliantSignedOrder.makerAssetAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(compliantSignedOrder.takerAssetAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), + ); + // Maker #2 + expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), + ); + expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), + ); + // Taker + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + // Fee recipient + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(compliantSignedOrder.makerFee).add(makerFeePaid2).add(takerFeePaid), + ); + }); + it('should revert if one maker does not meet the balance threshold', async () => { + // Create order set with one non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + makerAddress: nonCompliantAddress + }); + const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + // Execute transaction + const dummyMakerAssetFillAmount = new BigNumber(0); + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync( + orders, + compliantTakerAddress, + {makerAssetFillAmount: dummyMakerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const dummyMakerAssetFillAmount = new BigNumber(0); + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.marketBuyOrdersAsync( + orders, + nonCompliantAddress, + {makerAssetFillAmount: dummyMakerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('marketBuyOrdersNoThrowAsync', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { + // Execute a valid fill + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); + const makerAssetFillAmount2 = takerAssetFillAmount + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, compliantTakerAddress, {makerAssetFillAmount: cumulativeMakerAssetFillAmount}); + // Assert validated addresses + const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + const makerFeePaid2 = compliantSignedOrder2.makerFee + .times(makerAssetFillAmount2) + .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); + const takerFeePaid2 = compliantSignedOrder2.takerFee + .times(makerAssetFillAmount2) + .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); + const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); + // Maker #1 + expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(compliantSignedOrder.makerAssetAmount), + ); + expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(compliantSignedOrder.takerAssetAmount), + ); + expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), + ); + // Maker #2 + expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), + ); + expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + ); + expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), + ); + // Taker + expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), + ); + expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + ); + // Fee recipient + expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(compliantSignedOrder.makerFee).add(makerFeePaid2).add(takerFeePaid), + ); + }); + it('should revert if one maker does not meet the balance threshold', async () => { + // Create order set with one non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + makerAddress: nonCompliantAddress + }); + const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + // Execute transaction + const dummyMakerAssetFillAmount = new BigNumber(0); + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync( + orders, + compliantTakerAddress, + {makerAssetFillAmount: dummyMakerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + const orders = [compliantSignedOrder, compliantSignedOrder2]; + const dummyMakerAssetFillAmount = new BigNumber(0); + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync( + orders, + nonCompliantAddress, + {makerAssetFillAmount: dummyMakerAssetFillAmount} + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('matchOrders', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('Should transfer correct amounts when both makers and taker meet the balance threshold', async () => { + // Test values/results taken from Match Orders test: + // 'Should transfer correct amounts when right order is fully filled and values pass isRoundingErrorFloor but fail isRoundingErrorCeil' + // Create orders to match + const signedOrderLeft = await orderFactory.newSignedOrderAsync({ + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(17), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(98), 0), + makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + feeRecipientAddress: feeRecipientAddress, + }); + const signedOrderRight = await orderFactory2.newSignedOrderAsync({ + makerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), + takerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), + makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), + feeRecipientAddress: feeRecipientAddress, + }); + // Compute expected transfer amounts + const expectedTransferAmounts = { + // Left Maker + amountSoldByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + amountBoughtByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + feePaidByLeftMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.4705882352941176'), 16), // 76.47% + // Right Maker + amountSoldByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), + amountBoughtByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), + feePaidByRightMaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + // Taker + amountReceivedByTaker: Web3Wrapper.toBaseUnitAmount(new BigNumber(0), 0), + feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53% + feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% + }; + const txReceipt = await erc721TakerBalanceThresholdWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, compliantTakerAddress); + // Assert validated addresses + const expectedValidatedAddresseses = [signedOrderLeft.makerAddress, signedOrderRight.makerAddress, compliantTakerAddress]; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check balances + const newBalances = await erc20Wrapper.getBalancesAsync(); + expect( + newBalances[signedOrderLeft.makerAddress][defaultMakerAssetAddress], + 'Checking left maker egress ERC20 account balance', + ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][defaultMakerAssetAddress].sub(expectedTransferAmounts.amountSoldByLeftMaker)); + expect( + newBalances[signedOrderRight.makerAddress][defaultTakerAssetAddress], + 'Checking right maker ingress ERC20 account balance', + ).to.be.bignumber.equal(erc20Balances[signedOrderRight.makerAddress][defaultTakerAssetAddress].sub(expectedTransferAmounts.amountSoldByRightMaker)); + expect( + newBalances[compliantTakerAddress][defaultMakerAssetAddress], + 'Checking taker ingress ERC20 account balance', + ).to.be.bignumber.equal(erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(expectedTransferAmounts.amountReceivedByTaker)); + expect( + newBalances[signedOrderLeft.makerAddress][defaultTakerAssetAddress], + 'Checking left maker ingress ERC20 account balance', + ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][defaultTakerAssetAddress].add(expectedTransferAmounts.amountBoughtByLeftMaker)); + expect( + newBalances[signedOrderRight.makerAddress][defaultMakerAssetAddress], + 'Checking right maker egress ERC20 account balance', + ).to.be.bignumber.equal( + erc20Balances[signedOrderRight.makerAddress][defaultMakerAssetAddress].add(expectedTransferAmounts.amountBoughtByRightMaker), + ); + // Paid fees + expect( + newBalances[signedOrderLeft.makerAddress][zrxToken.address], + 'Checking left maker egress ERC20 account fees', + ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByLeftMaker)); + expect( + newBalances[signedOrderRight.makerAddress][zrxToken.address], + 'Checking right maker egress ERC20 account fees', + ).to.be.bignumber.equal(erc20Balances[signedOrderRight.makerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByRightMaker)); + expect( + newBalances[compliantTakerAddress][zrxToken.address], + 'Checking taker egress ERC20 account fees', + ).to.be.bignumber.equal(erc20Balances[compliantTakerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByTakerLeft).sub(expectedTransferAmounts.feePaidByTakerRight)); + // Received fees + expect( + newBalances[signedOrderLeft.feeRecipientAddress][zrxToken.address], + 'Checking left fee recipient ingress ERC20 account fees', + ).to.be.bignumber.equal( + erc20Balances[feeRecipientAddress][zrxToken.address].add(expectedTransferAmounts.feePaidByLeftMaker).add(expectedTransferAmounts.feePaidByRightMaker).add(expectedTransferAmounts.feePaidByTakerLeft).add(expectedTransferAmounts.feePaidByTakerRight), + ); + }); + it('should revert if left maker does not meet the balance threshold', async () => { + // Create signed order with non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + senderAddress: erc721CompliantForwarderInstance.address, + makerAddress: nonCompliantAddress + }); + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.matchOrdersAsync( + compliantSignedOrder, + signedOrderWithBadMakerAddress, + compliantTakerAddress, + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if right maker does not meet the balance threshold', async () => { + // Create signed order with non-compliant maker address + const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ + senderAddress: erc721CompliantForwarderInstance.address, + makerAddress: nonCompliantAddress + }); + // Execute transaction + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.matchOrdersAsync( + signedOrderWithBadMakerAddress, + compliantSignedOrder, + compliantTakerAddress, + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + it('should revert if taker does not meet the balance threshold', async () => { + return expectTransactionFailedAsync( + erc721NonCompliantBalanceThresholdWrapper.matchOrdersAsync( + compliantSignedOrder, + compliantSignedOrder, + nonCompliantAddress, + ), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + ); + }); + }); + + describe('cancelOrder', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + }); + it('Should successfully cancel order if maker meets balance threshold', async () => { + // Verify order is not cancelled + const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); + // Cancel + const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrderAsync(compliantSignedOrder, compliantSignedOrder.makerAddress); + // Assert validated addresses + const expectedValidatedAddresseses: string[] = []; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check that order was cancelled + const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); + }); + it('Should successfully cancel order if maker does not meet balance threshold', async () => { + // Create order where maker does not meet balance threshold + const signedOrderWithBadMakerAddress = await nonCompliantOrderFactory.newSignedOrderAsync({}); + // Verify order is not cancelled + const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(signedOrderWithBadMakerAddress) + expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); + // Cancel + const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.cancelOrderAsync(signedOrderWithBadMakerAddress, signedOrderWithBadMakerAddress.makerAddress); + // Assert validated addresses + const expectedValidatedAddresseses: string[] = []; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check that order was cancelled + const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(signedOrderWithBadMakerAddress) + expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); + }); + }); + + describe('batchCancelOrders', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + }); + it('Should successfully batch cancel orders if maker meets balance threshold', async () => { + // Create orders to cancel + const compliantSignedOrders = [ + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + await orderFactory.newSignedOrderAsync(), + ]; + // Verify orders are not cancelled + await _.each(compliantSignedOrders, async (compliantSignedOrder) => { + const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); + }); + // Cancel + const txReceipt = await erc721MakerBalanceThresholdWrapper.batchCancelOrdersAsync(compliantSignedOrders, compliantSignedOrder.makerAddress); + // Assert validated addresses + const expectedValidatedAddresseses: string[] = []; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check that order was cancelled + await _.each(compliantSignedOrders, async (compliantSignedOrder) => { + const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); + }); + }); + it('Should successfully batch cancel order if maker does not meet balance threshold', async () => { + // Create orders to cancel + const nonCompliantSignedOrders = [ + await nonCompliantOrderFactory.newSignedOrderAsync(), + await nonCompliantOrderFactory.newSignedOrderAsync(), + await nonCompliantOrderFactory.newSignedOrderAsync(), + ]; + // Verify orders are not cancelled + await _.each(nonCompliantSignedOrders, async (nonCompliantSignedOrder) => { + const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(nonCompliantSignedOrder) + return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); + }); + // Cancel + const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.batchCancelOrdersAsync(nonCompliantSignedOrders, nonCompliantAddress); + // Assert validated addresses + const expectedValidatedAddresseses: string[] = []; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check that order was cancelled + await _.each(nonCompliantSignedOrders, async (nonCompliantSignedOrder) => { + const orderInfoAfterCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(nonCompliantSignedOrder) + return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); + }); + }); + }); + + describe('cancelOrdersUpTo', () => { + beforeEach(async () => { + erc20Balances = await erc20Wrapper.getBalancesAsync(); + }); + it('Should successfully batch cancel orders if maker meets balance threshold', async () => { + // Create orders to cancel + const compliantSignedOrders = [ + await orderFactory.newSignedOrderAsync({salt: new BigNumber(0)}), + await orderFactory.newSignedOrderAsync({salt: new BigNumber(1)}), + await orderFactory.newSignedOrderAsync({salt: new BigNumber(2)}), + ]; + // Verify orders are not cancelled + await _.each(compliantSignedOrders, async (compliantSignedOrder) => { + const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); + }); + // Cancel + const cancelOrdersUpToThisSalt = new BigNumber(1); + const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrdersUpToAsync(cancelOrdersUpToThisSalt, compliantSignedOrder.makerAddress); + // Assert validated addresses + const expectedValidatedAddresseses: string[] = []; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check that order was cancelled + await _.each(compliantSignedOrders, async (compliantSignedOrder, salt: number) => { + const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + const saltAsBigNumber = new BigNumber(salt); + if (saltAsBigNumber.lessThanOrEqualTo(cancelOrdersUpToThisSalt)) { + return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); + } else { + return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); + } + }); + }); + it('Should successfully batch cancel order if maker does not meet balance threshold', async () => { + // Create orders to cancel + const nonCompliantSignedOrders = [ + await nonCompliantOrderFactory.newSignedOrderAsync({salt: new BigNumber(0)}), + await nonCompliantOrderFactory.newSignedOrderAsync({salt: new BigNumber(1)}), + await nonCompliantOrderFactory.newSignedOrderAsync({salt: new BigNumber(2)}), + ]; + // Verify orders are not cancelled + await _.each(nonCompliantSignedOrders, async (nonCompliantSignedOrder) => { + const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(nonCompliantSignedOrder) + return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); + }); + // Cancel + const cancelOrdersUpToThisSalt = new BigNumber(1); + const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.cancelOrdersUpToAsync(cancelOrdersUpToThisSalt, nonCompliantAddress); + // Assert validated addresses + const expectedValidatedAddresseses: string[] = []; + assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + // Check that order was cancelled + await _.each(nonCompliantSignedOrders, async (nonCompliantSignedOrder, salt: number) => { + const orderInfoAfterCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(nonCompliantSignedOrder) + const saltAsBigNumber = new BigNumber(salt); + if (saltAsBigNumber.lessThanOrEqualTo(cancelOrdersUpToThisSalt)) { + return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); + } else { + return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); + } + }); + }); + }); +}); +// tslint:disable:max-file-line-count +// tslint:enable:no-unnecessary-type-assertion diff --git a/contracts/extensions/test/utils/balance_threshold_wrapper.ts b/contracts/extensions/test/utils/balance_threshold_wrapper.ts new file mode 100644 index 000000000..63128686c --- /dev/null +++ b/contracts/extensions/test/utils/balance_threshold_wrapper.ts @@ -0,0 +1,246 @@ +import { SignedOrder } from '@0x/types'; +import { BigNumber } from '@0x/utils'; +import { Web3Wrapper } from '@0x/web3-wrapper'; +import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; +import * as _ from 'lodash'; + +import { ExchangeContract } from '@0x/contracts-protocol'; +import { BalanceThresholdFilterContract } from '../../generated-wrappers/balance_threshold_filter'; + +import { formatters, LogDecoder, orderUtils, OrderInfo, TransactionFactory } from '@0x/contracts-test-utils'; +import { artifacts } from '../../src/artifacts'; +import {artifacts as protocolArtifacts} from '@0x/contracts-protocol'; +import { artifacts as tokensArtifacts } from '@0x/contracts-tokens'; + +export class BalanceThresholdWrapper { + private readonly _balanceThresholdFilter: BalanceThresholdFilterContract; + private readonly _signerTransactionFactory: TransactionFactory; + private readonly _exchange: ExchangeContract; + private readonly _web3Wrapper: Web3Wrapper; + private readonly _logDecoder: LogDecoder; + constructor(balanceThresholdFilter: BalanceThresholdFilterContract, exchangeContract: ExchangeContract, signerTransactionFactory: TransactionFactory, provider: Provider) { + this._balanceThresholdFilter = balanceThresholdFilter; + this._exchange = exchangeContract; + this._signerTransactionFactory = signerTransactionFactory; + this._web3Wrapper = new Web3Wrapper(provider); + this._logDecoder = new LogDecoder(this._web3Wrapper, {... artifacts, ... tokensArtifacts, ... protocolArtifacts} ); + } + public async fillOrderAsync( + signedOrder: SignedOrder, + from: string, + opts: { takerAssetFillAmount?: BigNumber } = {}, + ): Promise { + const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount); + const data = this._exchange.fillOrder.getABIEncodedTransactionData( + params.order, + params.takerAssetFillAmount, + params.signature, + ); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async fillOrKillOrderAsync( + signedOrder: SignedOrder, + from: string, + opts: { takerAssetFillAmount?: BigNumber } = {}, + ): Promise { + const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount); + const data = this._exchange.fillOrKillOrder.getABIEncodedTransactionData( + params.order, + params.takerAssetFillAmount, + params.signature, + ); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async fillOrderNoThrowAsync( + signedOrder: SignedOrder, + from: string, + opts: { takerAssetFillAmount?: BigNumber; gas?: number } = {}, + ): Promise { + const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount); + const data = this._exchange.fillOrderNoThrow.getABIEncodedTransactionData( + params.order, + params.takerAssetFillAmount, + params.signature, + ); + const txReceipt = this._executeTransaction(data, from, opts.gas); + return txReceipt; + } + public async batchFillOrdersAsync( + orders: SignedOrder[], + from: string, + opts: { takerAssetFillAmounts?: BigNumber[] } = {}, + ): Promise { + const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts); + const data = this._exchange.batchFillOrders.getABIEncodedTransactionData( + params.orders, + params.takerAssetFillAmounts, + params.signatures, + ); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async batchFillOrKillOrdersAsync( + orders: SignedOrder[], + from: string, + opts: { takerAssetFillAmounts?: BigNumber[] } = {}, + ): Promise { + const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts); + const data = this._exchange.batchFillOrKillOrders.getABIEncodedTransactionData( + params.orders, + params.takerAssetFillAmounts, + params.signatures, + ); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async batchFillOrdersNoThrowAsync( + orders: SignedOrder[], + from: string, + opts: { takerAssetFillAmounts?: BigNumber[]; gas?: number } = {}, + ): Promise { + const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts); + const data = this._exchange.batchFillOrKillOrders.getABIEncodedTransactionData( + params.orders, + params.takerAssetFillAmounts, + params.signatures, + ); + const txReceipt = this._executeTransaction(data, from, opts.gas); + return txReceipt; + } + public async marketSellOrdersAsync( + orders: SignedOrder[], + from: string, + opts: { takerAssetFillAmount: BigNumber }, + ): Promise { + const params = formatters.createMarketSellOrders(orders, opts.takerAssetFillAmount); + const data = this._exchange.marketSellOrders.getABIEncodedTransactionData( + params.orders, + params.takerAssetFillAmount, + params.signatures, + ); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async marketSellOrdersNoThrowAsync( + orders: SignedOrder[], + from: string, + opts: { takerAssetFillAmount: BigNumber; gas?: number }, + ): Promise { + const params = formatters.createMarketSellOrders(orders, opts.takerAssetFillAmount); + const data = this._exchange.marketSellOrdersNoThrow.getABIEncodedTransactionData( + params.orders, + params.takerAssetFillAmount, + params.signatures, + ); + const txReceipt = this._executeTransaction(data, from, opts.gas); + return txReceipt; + } + public async marketBuyOrdersAsync( + orders: SignedOrder[], + from: string, + opts: { makerAssetFillAmount: BigNumber }, + ): Promise { + const params = formatters.createMarketBuyOrders(orders, opts.makerAssetFillAmount); + const data = this._exchange.marketBuyOrders.getABIEncodedTransactionData( + params.orders, + params.makerAssetFillAmount, + params.signatures, + ); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async marketBuyOrdersNoThrowAsync( + orders: SignedOrder[], + from: string, + opts: { makerAssetFillAmount: BigNumber; gas?: number }, + ): Promise { + const params = formatters.createMarketBuyOrders(orders, opts.makerAssetFillAmount); + const data = this._exchange.marketBuyOrdersNoThrow.getABIEncodedTransactionData( + params.orders, + params.makerAssetFillAmount, + params.signatures, + ); + const txReceipt = this._executeTransaction(data, from, opts.gas); + return txReceipt; + } + public async cancelOrderAsync(signedOrder: SignedOrder, from: string): Promise { + const params = orderUtils.createCancel(signedOrder); + const data = this._exchange.cancelOrder.getABIEncodedTransactionData(params.order); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async batchCancelOrdersAsync( + orders: SignedOrder[], + from: string, + ): Promise { + const params = formatters.createBatchCancel(orders); + const data = this._exchange.batchCancelOrders.getABIEncodedTransactionData(params.orders); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async cancelOrdersUpToAsync(salt: BigNumber, from: string): Promise { + const data = this._exchange.cancelOrdersUpTo.getABIEncodedTransactionData(salt); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise { + const filledAmount = await this._exchange.filled.callAsync(orderHashHex); + return filledAmount; + } + public async isCancelledAsync(orderHashHex: string): Promise { + const isCancelled = await this._exchange.cancelled.callAsync(orderHashHex); + return isCancelled; + } + public async getOrderEpochAsync(makerAddress: string, senderAddress: string): Promise { + const orderEpoch = await this._exchange.orderEpoch.callAsync(makerAddress, senderAddress); + return orderEpoch; + } + public async getOrderInfoAsync(signedOrder: SignedOrder): Promise { + const orderInfo = (await this._exchange.getOrderInfo.callAsync(signedOrder)) as OrderInfo; + return orderInfo; + } + public async getOrdersInfoAsync(signedOrders: SignedOrder[]): Promise { + const ordersInfo = (await this._exchange.getOrdersInfo.callAsync(signedOrders)) as OrderInfo[]; + return ordersInfo; + } + public async matchOrdersAsync( + signedOrderLeft: SignedOrder, + signedOrderRight: SignedOrder, + from: string, + ): Promise { + const params = orderUtils.createMatchOrders(signedOrderLeft, signedOrderRight); + const data = await this._exchange.matchOrders.getABIEncodedTransactionData( + params.left, + params.right, + params.leftSignature, + params.rightSignature + ); + const txReceipt = this._executeTransaction(data, from); + return txReceipt; + } + public getBalanceThresholdAddress(): string { + return this._balanceThresholdFilter.address; + } + public getExchangeAddress(): string { + return this._exchange.address; + } + // Exchange functions + //abiEncodeFillOrder + //getFillOrderResultsAsync + // + private async _executeTransaction(abiEncodedExchangeTxData: string, from: string, gas?: number): Promise { + const signedExchangeTx = this._signerTransactionFactory.newSignedTransaction(abiEncodedExchangeTxData); + const txOpts = _.isUndefined(gas) ? {from} : {from, gas}; + const txHash = await this._balanceThresholdFilter.executeTransaction.sendTransactionAsync( + signedExchangeTx.salt, + signedExchangeTx.signerAddress, + signedExchangeTx.data, + signedExchangeTx.signature, + txOpts, + ); + const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); + return txReceipt; + } +} diff --git a/contracts/extensions/tsconfig.json b/contracts/extensions/tsconfig.json index a4ce1e002..5d3ebfe74 100644 --- a/contracts/extensions/tsconfig.json +++ b/contracts/extensions/tsconfig.json @@ -6,6 +6,6 @@ "resolveJsonModule": true }, "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], - "files": ["./generated-artifacts/DutchAuction.json", "./generated-artifacts/Forwarder.json"], + "files": ["./generated-artifacts/BalanceThresholdFilter.json", "./generated-artifacts/DutchAuction.json", "./generated-artifacts/Forwarder.json"], "exclude": ["./deploy/solc/solc_bin"] } -- cgit v1.2.3 From 6a0f5f39eea5fef285a1e2e962be03c2fa8847ab Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 11 Dec 2018 15:55:36 -0800 Subject: Prettier / Linter fixes for TS --- .../test/extensions/balance_threshold_filter.ts | 779 +++++++++++++-------- contracts/extensions/test/extensions/forwarder.ts | 1 - .../test/utils/balance_threshold_wrapper.ts | 95 ++- contracts/extensions/tsconfig.json | 6 +- 4 files changed, 543 insertions(+), 338 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts index 34339564c..e4eda3354 100644 --- a/contracts/extensions/test/extensions/balance_threshold_filter.ts +++ b/contracts/extensions/test/extensions/balance_threshold_filter.ts @@ -1,12 +1,12 @@ import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils } from '@0x/order-utils'; -import { RevertReason, SignedOrder, Order } from '@0x/types'; +import { Order, RevertReason, SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import * as chai from 'chai'; +import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; -import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { artifacts as protocolArtifacts, @@ -14,7 +14,6 @@ import { ERC721Wrapper, ExchangeContract, ExchangeWrapper, - TestExchangeInternalsContract, } from '@0x/contracts-protocol'; import { chaiSetup, @@ -23,26 +22,19 @@ import { ERC20BalancesByOwner, expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync, - getLatestBlockTimestampAsync, - LogDecoder, OrderFactory, OrderStatus, orderUtils, provider, SignedTransaction, - txDefaults, TransactionFactory, + txDefaults, web3Wrapper, } from '@0x/contracts-test-utils'; -import { - artifacts as tokensArtifacts, - DummyERC20TokenContract, - DummyERC721TokenContract, - WETH9Contract, -} from '@0x/contracts-tokens'; +import { DummyERC20TokenContract } from '@0x/contracts-tokens'; -import { artifacts } from '../../src/artifacts'; import { BalanceThresholdFilterContract } from '../../generated-wrappers/balance_threshold_filter'; +import { artifacts } from '../../src/artifacts'; import { BalanceThresholdWrapper } from '../utils/balance_threshold_wrapper'; chaiSetup.configure(); @@ -51,7 +43,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const DECIMALS_DEFAULT = 18; interface ValidatedAddressesLog { - args: {addresses: string[]} + args: { addresses: string[] }; } describe.only(ContractName.BalanceThresholdFilter, () => { @@ -79,14 +71,10 @@ describe.only(ContractName.BalanceThresholdFilter, () => { let erc721NonCompliantBalanceThresholdWrapper: BalanceThresholdWrapper; let takerTransactionFactory: TransactionFactory; - let makerTransactionFactory: TransactionFactory; let compliantSignedOrder: SignedOrder; let compliantSignedOrder2: SignedOrder; let compliantSignedFillOrderTx: SignedTransaction; - let logDecoder: LogDecoder; - let exchangeInternals: TestExchangeInternalsContract; - let defaultOrderParams: Partial; const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT); @@ -96,14 +84,17 @@ describe.only(ContractName.BalanceThresholdFilter, () => { let erc721CompliantForwarderInstance: BalanceThresholdFilterContract; let erc20CompliantForwarderInstance: BalanceThresholdFilterContract; - const assertValidatedAddressesLog = async (txReceipt: TransactionReceiptWithDecodedLogs, expectedValidatedAddresses: string[]) => { + const assertValidatedAddressesLog = async ( + txReceipt: TransactionReceiptWithDecodedLogs, + expectedValidatedAddresses: string[], + ) => { expect(txReceipt.logs.length).to.be.gte(1); const validatedAddressesLog = (txReceipt.logs[0] as any) as ValidatedAddressesLog; const validatedAddresses = validatedAddressesLog.args.addresses; // @HACK-hysz: Nested addresses are not translated to lower-case but this will change once // the new ABI Encoder/Decoder is used by the contract templates. - let validatedAddressesNormalized: string[] = []; - _.each(validatedAddresses, (address) => { + const validatedAddressesNormalized: string[] = []; + _.each(validatedAddresses, address => { const normalizedAddress = _.toLower(address); validatedAddressesNormalized.push(normalizedAddress); }); @@ -124,7 +115,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { ] = accounts); // Create wrappers erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); - let compliantAddresses = _.cloneDeepWith(usedAddresses); + const compliantAddresses = _.cloneDeepWith(usedAddresses); _.remove(compliantAddresses, (address: string) => { return address === nonCompliantAddress; }); @@ -168,7 +159,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { txDefaults, exchangeInstance.address, erc721BalanceThresholdAsset.address, - erc721alanceThreshold + erc721alanceThreshold, ); const erc20BalanceThreshold = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 10); erc20CompliantForwarderInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync( @@ -177,7 +168,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { txDefaults, exchangeInstance.address, erc20BalanceThresholdAsset.address, - erc20BalanceThreshold + erc20BalanceThreshold, ); // Default order parameters @@ -194,25 +185,22 @@ describe.only(ContractName.BalanceThresholdFilter, () => { }; const defaultOrderParams1 = { makerAddress: compliantMakerAddress, - ... - defaultOrderParams, - } + ...defaultOrderParams, + }; const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantMakerAddress)]; takerTransactionFactory = new TransactionFactory(makerPrivateKey, exchangeInstance.address); orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams1); const defaultOrderParams2 = { makerAddress: compliantMakerAddress2, - ... - defaultOrderParams, - } + ...defaultOrderParams, + }; const secondMakerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantMakerAddress2)]; orderFactory2 = new OrderFactory(secondMakerPrivateKey, defaultOrderParams2); const nonCompliantPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(nonCompliantAddress)]; const defaultNonCompliantOrderParams = { makerAddress: nonCompliantAddress, - ... - defaultOrderParams, + ...defaultOrderParams, }; nonCompliantOrderFactory = new OrderFactory(nonCompliantPrivateKey, defaultNonCompliantOrderParams); // Create Valid/Invalid orders @@ -233,17 +221,29 @@ describe.only(ContractName.BalanceThresholdFilter, () => { compliantSignedOrderWithoutExchangeAddressData, ); - logDecoder = new LogDecoder(web3Wrapper, {... artifacts, ... protocolArtifacts, ... tokensArtifacts}); - erc20TakerBalanceThresholdWrapper = new BalanceThresholdWrapper(erc20CompliantForwarderInstance, exchangeInstance, new TransactionFactory(takerPrivateKey, exchangeInstance.address), provider); - erc721TakerBalanceThresholdWrapper = new BalanceThresholdWrapper(erc721CompliantForwarderInstance, exchangeInstance, new TransactionFactory(takerPrivateKey, exchangeInstance.address), provider); - erc721MakerBalanceThresholdWrapper = new BalanceThresholdWrapper(erc721CompliantForwarderInstance, exchangeInstance, new TransactionFactory(makerPrivateKey, exchangeInstance.address), provider); - erc721NonCompliantBalanceThresholdWrapper = new BalanceThresholdWrapper(erc721CompliantForwarderInstance, exchangeInstance, new TransactionFactory(nonCompliantPrivateKey, exchangeInstance.address), provider); - - // Instantiate internal exchange contract - exchangeInternals = await TestExchangeInternalsContract.deployFrom0xArtifactAsync( - protocolArtifacts.TestExchangeInternals, + erc20TakerBalanceThresholdWrapper = new BalanceThresholdWrapper( + erc20CompliantForwarderInstance, + exchangeInstance, + new TransactionFactory(takerPrivateKey, exchangeInstance.address), + provider, + ); + erc721TakerBalanceThresholdWrapper = new BalanceThresholdWrapper( + erc721CompliantForwarderInstance, + exchangeInstance, + new TransactionFactory(takerPrivateKey, exchangeInstance.address), + provider, + ); + erc721MakerBalanceThresholdWrapper = new BalanceThresholdWrapper( + erc721CompliantForwarderInstance, + exchangeInstance, + new TransactionFactory(makerPrivateKey, exchangeInstance.address), + provider, + ); + erc721NonCompliantBalanceThresholdWrapper = new BalanceThresholdWrapper( + erc721CompliantForwarderInstance, + exchangeInstance, + new TransactionFactory(nonCompliantPrivateKey, exchangeInstance.address), provider, - txDefaults, ); }); beforeEach(async () => { @@ -261,16 +261,22 @@ describe.only(ContractName.BalanceThresholdFilter, () => { }); it('should transfer the correct amounts and validate both maker/taker when both maker and taker exceed the balance threshold of an ERC20 token', async () => { const compliantSignedOrderERC20Sender = await orderFactory.newSignedOrderAsync({ - ... - defaultOrderParams, + ...defaultOrderParams, makerAddress: compliantMakerAddress, senderAddress: erc20TakerBalanceThresholdWrapper.getBalanceThresholdAddress(), }); // Execute a valid fill - const txReceipt = await erc20TakerBalanceThresholdWrapper.fillOrderAsync(compliantSignedOrderERC20Sender, compliantTakerAddress, {takerAssetFillAmount}); + const txReceipt = await erc20TakerBalanceThresholdWrapper.fillOrderAsync( + compliantSignedOrderERC20Sender, + compliantTakerAddress, + { takerAssetFillAmount }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount = takerAssetFillAmount @@ -314,12 +320,14 @@ describe.only(ContractName.BalanceThresholdFilter, () => { const txDataBufWithBadSelector = Buffer.concat([badSelectorBuf, txDataBufMinusSelector]); const txDataBufWithBadSelectorHex = ethUtil.bufferToHex(txDataBufWithBadSelector); // Call compliant forwarder - return expectTransactionFailedWithoutReasonAsync(erc721CompliantForwarderInstance.executeTransaction.sendTransactionAsync( - compliantSignedFillOrderTx.salt, - compliantSignedFillOrderTx.signerAddress, - txDataBufWithBadSelectorHex, - compliantSignedFillOrderTx.signature, - )); + return expectTransactionFailedWithoutReasonAsync( + erc721CompliantForwarderInstance.executeTransaction.sendTransactionAsync( + compliantSignedFillOrderTx.salt, + compliantSignedFillOrderTx.signerAddress, + txDataBufWithBadSelectorHex, + compliantSignedFillOrderTx.signature, + ), + ); }); it('should revert if senderAddress is not set to the compliant forwarding contract', async () => { // Create signed order with incorrect senderAddress @@ -339,12 +347,14 @@ describe.only(ContractName.BalanceThresholdFilter, () => { signedOrderWithoutExchangeAddressData, ); // Call compliant forwarder - return expectTransactionFailedWithoutReasonAsync(erc721CompliantForwarderInstance.executeTransaction.sendTransactionAsync( - signedFillOrderTx.salt, - signedFillOrderTx.signerAddress, - signedFillOrderTx.data, - signedFillOrderTx.signature, - )); + return expectTransactionFailedWithoutReasonAsync( + erc721CompliantForwarderInstance.executeTransaction.sendTransactionAsync( + signedFillOrderTx.salt, + signedFillOrderTx.signerAddress, + signedFillOrderTx.data, + signedFillOrderTx.signature, + ), + ); }); // @TODO - greater than 1 balance }); @@ -359,10 +369,18 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Execute a valid fill const orders = [compliantSignedOrder, compliantSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; - const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync(orders, compliantTakerAddress, {takerAssetFillAmounts}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync( + orders, + compliantTakerAddress, + { takerAssetFillAmounts }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedOrder2.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); @@ -396,11 +414,11 @@ describe.only(ContractName.BalanceThresholdFilter, () => { expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), ); - // Taker + // Taker expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), ); @@ -416,29 +434,25 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Create order set with one non-compliant maker address const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync( - orders, - compliantTakerAddress, - {takerAssetFillAmounts} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync(orders, compliantTakerAddress, { + takerAssetFillAmounts, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.batchFillOrdersAsync( - orders, - nonCompliantAddress, - {takerAssetFillAmounts} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721NonCompliantBalanceThresholdWrapper.batchFillOrdersAsync(orders, nonCompliantAddress, { + takerAssetFillAmounts, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); @@ -453,10 +467,18 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Execute a valid fill const orders = [compliantSignedOrder, compliantSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; - const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, compliantTakerAddress, {takerAssetFillAmounts}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync( + orders, + compliantTakerAddress, + { takerAssetFillAmounts }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedOrder2.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); @@ -490,11 +512,11 @@ describe.only(ContractName.BalanceThresholdFilter, () => { expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), ); - // Taker + // Taker expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), ); @@ -510,29 +532,25 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Create order set with one non-compliant maker address const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync( - orders, - compliantTakerAddress, - {takerAssetFillAmounts} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, compliantTakerAddress, { + takerAssetFillAmounts, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.batchFillOrdersNoThrowAsync( - orders, - nonCompliantAddress, - {takerAssetFillAmounts} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721NonCompliantBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, nonCompliantAddress, { + takerAssetFillAmounts, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); @@ -547,10 +565,18 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Execute a valid fill const orders = [compliantSignedOrder, compliantSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; - const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, compliantTakerAddress, {takerAssetFillAmounts}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync( + orders, + compliantTakerAddress, + { takerAssetFillAmounts }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedOrder2.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); @@ -584,11 +610,11 @@ describe.only(ContractName.BalanceThresholdFilter, () => { expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), ); - // Taker + // Taker expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - + expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), ); @@ -604,29 +630,25 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Create order set with one non-compliant maker address const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync( - orders, - compliantTakerAddress, - {takerAssetFillAmounts} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, compliantTakerAddress, { + takerAssetFillAmounts, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.batchFillOrKillOrdersAsync( - orders, - nonCompliantAddress, - {takerAssetFillAmounts} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721NonCompliantBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, nonCompliantAddress, { + takerAssetFillAmounts, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if one takerAssetFillAmount is not fully filled', async () => { @@ -634,12 +656,10 @@ describe.only(ContractName.BalanceThresholdFilter, () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, tooBigTakerAssetFillAmount]; return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync( - orders, - compliantTakerAddress, - {takerAssetFillAmounts} - ), - RevertReason.FailedExecution + erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, compliantTakerAddress, { + takerAssetFillAmounts, + }), + RevertReason.FailedExecution, ); }); }); @@ -651,10 +671,17 @@ describe.only(ContractName.BalanceThresholdFilter, () => { }); it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { // Execute a valid fill - const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderAsync(compliantSignedOrder, compliantTakerAddress, {takerAssetFillAmount}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderAsync( + compliantSignedOrder, + compliantTakerAddress, + { takerAssetFillAmount }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount = takerAssetFillAmount @@ -692,26 +719,24 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Create signed order with non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.fillOrderAsync( signedOrderWithBadMakerAddress, - compliantTakerAddress, - {takerAssetFillAmount} + compliantTakerAddress, + { takerAssetFillAmount }, ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.fillOrderAsync( - compliantSignedOrder, - nonCompliantAddress, - {takerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721NonCompliantBalanceThresholdWrapper.fillOrderAsync(compliantSignedOrder, nonCompliantAddress, { + takerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); @@ -723,10 +748,17 @@ describe.only(ContractName.BalanceThresholdFilter, () => { }); it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { // Execute a valid fill - const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync(compliantSignedOrder, compliantTakerAddress, {takerAssetFillAmount}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync( + compliantSignedOrder, + compliantTakerAddress, + { takerAssetFillAmount }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount = takerAssetFillAmount @@ -764,26 +796,26 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Create signed order with non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync( signedOrderWithBadMakerAddress, - compliantTakerAddress, - {takerAssetFillAmount} + compliantTakerAddress, + { takerAssetFillAmount }, ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( erc721NonCompliantBalanceThresholdWrapper.fillOrderNoThrowAsync( compliantSignedOrder, - nonCompliantAddress, - {takerAssetFillAmount} + nonCompliantAddress, + { takerAssetFillAmount }, ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); @@ -796,10 +828,17 @@ describe.only(ContractName.BalanceThresholdFilter, () => { it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { // Execute a valid fill const takerAssetFillAmount_ = compliantSignedOrder.takerAssetAmount; - const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync(compliantSignedOrder, compliantTakerAddress, {takerAssetFillAmount: takerAssetFillAmount_}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync( + compliantSignedOrder, + compliantTakerAddress, + { takerAssetFillAmount: takerAssetFillAmount_ }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount = takerAssetFillAmount_ @@ -837,37 +876,35 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Create signed order with non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync( signedOrderWithBadMakerAddress, - compliantTakerAddress, - {takerAssetFillAmount} + compliantTakerAddress, + { takerAssetFillAmount }, ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( erc721NonCompliantBalanceThresholdWrapper.fillOrKillOrderAsync( compliantSignedOrder, - nonCompliantAddress, - {takerAssetFillAmount} + nonCompliantAddress, + { takerAssetFillAmount }, ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if takerAssetFillAmount is not fully filled', async () => { const tooBigTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.times(2); return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync( - compliantSignedOrder, - compliantTakerAddress, - {takerAssetFillAmount: tooBigTakerAssetFillAmount} - ), - RevertReason.FailedExecution + erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync(compliantSignedOrder, compliantTakerAddress, { + takerAssetFillAmount: tooBigTakerAssetFillAmount, + }), + RevertReason.FailedExecution, ); }); }); @@ -882,10 +919,18 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Execute a valid fill const orders = [compliantSignedOrder, compliantSignedOrder2]; const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); - const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync(orders, compliantTakerAddress, {takerAssetFillAmount: cumulativeTakerAssetFillAmount}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync( + orders, + compliantTakerAddress, + { takerAssetFillAmount: cumulativeTakerAssetFillAmount }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedOrder2.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount2 = takerAssetFillAmount @@ -901,10 +946,14 @@ describe.only(ContractName.BalanceThresholdFilter, () => { const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); // Maker #1 expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(compliantSignedOrder.makerAssetAmount), + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus( + compliantSignedOrder.makerAssetAmount, + ), ); expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(compliantSignedOrder.takerAssetAmount), + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add( + compliantSignedOrder.takerAssetAmount, + ), ); expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), @@ -919,7 +968,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), ); - // Taker + // Taker expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); @@ -931,34 +980,33 @@ describe.only(ContractName.BalanceThresholdFilter, () => { ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[feeRecipientAddress][zrxToken.address].add(compliantSignedOrder.makerFee).add(makerFeePaid2).add(takerFeePaid), + erc20Balances[feeRecipientAddress][zrxToken.address] + .add(compliantSignedOrder.makerFee) + .add(makerFeePaid2) + .add(takerFeePaid), ); }); it('should revert if one maker does not meet the balance threshold', async () => { // Create order set with one non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync( - orders, - compliantTakerAddress, - {takerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync(orders, compliantTakerAddress, { + takerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.marketSellOrdersAsync( - orders, - nonCompliantAddress, - {takerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721NonCompliantBalanceThresholdWrapper.marketSellOrdersAsync(orders, nonCompliantAddress, { + takerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); @@ -973,10 +1021,18 @@ describe.only(ContractName.BalanceThresholdFilter, () => { // Execute a valid fill const orders = [compliantSignedOrder, compliantSignedOrder2]; const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); - const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, compliantTakerAddress, {takerAssetFillAmount: cumulativeTakerAssetFillAmount}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync( + orders, + compliantTakerAddress, + { takerAssetFillAmount: cumulativeTakerAssetFillAmount }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedOrder2.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount2 = takerAssetFillAmount @@ -992,10 +1048,14 @@ describe.only(ContractName.BalanceThresholdFilter, () => { const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); // Maker #1 expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(compliantSignedOrder.makerAssetAmount), + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus( + compliantSignedOrder.makerAssetAmount, + ), ); expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(compliantSignedOrder.takerAssetAmount), + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add( + compliantSignedOrder.takerAssetAmount, + ), ); expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), @@ -1010,7 +1070,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), ); - // Taker + // Taker expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); @@ -1022,34 +1082,33 @@ describe.only(ContractName.BalanceThresholdFilter, () => { ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[feeRecipientAddress][zrxToken.address].add(compliantSignedOrder.makerFee).add(makerFeePaid2).add(takerFeePaid), + erc20Balances[feeRecipientAddress][zrxToken.address] + .add(compliantSignedOrder.makerFee) + .add(makerFeePaid2) + .add(takerFeePaid), ); }); it('should revert if one maker does not meet the balance threshold', async () => { // Create order set with one non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync( - orders, - compliantTakerAddress, - {takerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, compliantTakerAddress, { + takerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.marketSellOrdersNoThrowAsync( - orders, - nonCompliantAddress, - {takerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721NonCompliantBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, nonCompliantAddress, { + takerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); @@ -1065,13 +1124,21 @@ describe.only(ContractName.BalanceThresholdFilter, () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); const makerAssetFillAmount2 = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); - const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync(orders, compliantTakerAddress, {makerAssetFillAmount: cumulativeMakerAssetFillAmount}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync( + orders, + compliantTakerAddress, + { makerAssetFillAmount: cumulativeMakerAssetFillAmount }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedOrder2.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerFeePaid2 = compliantSignedOrder2.makerFee @@ -1083,10 +1150,14 @@ describe.only(ContractName.BalanceThresholdFilter, () => { const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); // Maker #1 expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(compliantSignedOrder.makerAssetAmount), + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus( + compliantSignedOrder.makerAssetAmount, + ), ); expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(compliantSignedOrder.takerAssetAmount), + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add( + compliantSignedOrder.takerAssetAmount, + ), ); expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), @@ -1101,7 +1172,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), ); - // Taker + // Taker expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); @@ -1113,36 +1184,35 @@ describe.only(ContractName.BalanceThresholdFilter, () => { ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[feeRecipientAddress][zrxToken.address].add(compliantSignedOrder.makerFee).add(makerFeePaid2).add(takerFeePaid), + erc20Balances[feeRecipientAddress][zrxToken.address] + .add(compliantSignedOrder.makerFee) + .add(makerFeePaid2) + .add(takerFeePaid), ); }); it('should revert if one maker does not meet the balance threshold', async () => { // Create order set with one non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction const dummyMakerAssetFillAmount = new BigNumber(0); return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync( - orders, - compliantTakerAddress, - {makerAssetFillAmount: dummyMakerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync(orders, compliantTakerAddress, { + makerAssetFillAmount: dummyMakerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; const dummyMakerAssetFillAmount = new BigNumber(0); return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.marketBuyOrdersAsync( - orders, - nonCompliantAddress, - {makerAssetFillAmount: dummyMakerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721NonCompliantBalanceThresholdWrapper.marketBuyOrdersAsync(orders, nonCompliantAddress, { + makerAssetFillAmount: dummyMakerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); @@ -1158,13 +1228,21 @@ describe.only(ContractName.BalanceThresholdFilter, () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); const makerAssetFillAmount2 = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); + .times(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); - const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, compliantTakerAddress, {makerAssetFillAmount: cumulativeMakerAssetFillAmount}); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync( + orders, + compliantTakerAddress, + { makerAssetFillAmount: cumulativeMakerAssetFillAmount }, + ); // Assert validated addresses - const expectedValidatedAddresseses = [compliantSignedOrder.makerAddress, compliantSignedOrder2.makerAddress, compliantSignedFillOrderTx.signerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + compliantSignedOrder.makerAddress, + compliantSignedOrder2.makerAddress, + compliantSignedFillOrderTx.signerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerFeePaid2 = compliantSignedOrder2.makerFee @@ -1176,10 +1254,14 @@ describe.only(ContractName.BalanceThresholdFilter, () => { const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); // Maker #1 expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(compliantSignedOrder.makerAssetAmount), + erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus( + compliantSignedOrder.makerAssetAmount, + ), ); expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(compliantSignedOrder.takerAssetAmount), + erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add( + compliantSignedOrder.takerAssetAmount, + ), ); expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), @@ -1194,7 +1276,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), ); - // Taker + // Taker expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); @@ -1206,40 +1288,39 @@ describe.only(ContractName.BalanceThresholdFilter, () => { ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[feeRecipientAddress][zrxToken.address].add(compliantSignedOrder.makerFee).add(makerFeePaid2).add(takerFeePaid), + erc20Balances[feeRecipientAddress][zrxToken.address] + .add(compliantSignedOrder.makerFee) + .add(makerFeePaid2) + .add(takerFeePaid), ); }); it('should revert if one maker does not meet the balance threshold', async () => { // Create order set with one non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction const dummyMakerAssetFillAmount = new BigNumber(0); return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync( - orders, - compliantTakerAddress, - {makerAssetFillAmount: dummyMakerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, compliantTakerAddress, { + makerAssetFillAmount: dummyMakerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { const orders = [compliantSignedOrder, compliantSignedOrder2]; const dummyMakerAssetFillAmount = new BigNumber(0); return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync( - orders, - nonCompliantAddress, - {makerAssetFillAmount: dummyMakerAssetFillAmount} - ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + erc721NonCompliantBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, nonCompliantAddress, { + makerAssetFillAmount: dummyMakerAssetFillAmount, + }), + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); - + describe('matchOrders', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); @@ -1255,7 +1336,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(98), 0), makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), - feeRecipientAddress: feeRecipientAddress, + feeRecipientAddress, }); const signedOrderRight = await orderFactory2.newSignedOrderAsync({ makerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), @@ -1264,7 +1345,7 @@ describe.only(ContractName.BalanceThresholdFilter, () => { takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), - feeRecipientAddress: feeRecipientAddress, + feeRecipientAddress, }); // Compute expected transfer amounts const expectedTransferAmounts = { @@ -1281,85 +1362,127 @@ describe.only(ContractName.BalanceThresholdFilter, () => { feePaidByTakerLeft: Web3Wrapper.toBaseUnitAmount(new BigNumber('76.5306122448979591'), 16), // 76.53% feePaidByTakerRight: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 16), // 100% }; - const txReceipt = await erc721TakerBalanceThresholdWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, compliantTakerAddress); + const txReceipt = await erc721TakerBalanceThresholdWrapper.matchOrdersAsync( + signedOrderLeft, + signedOrderRight, + compliantTakerAddress, + ); // Assert validated addresses - const expectedValidatedAddresseses = [signedOrderLeft.makerAddress, signedOrderRight.makerAddress, compliantTakerAddress]; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + const expectedValidatedAddresseses = [ + signedOrderLeft.makerAddress, + signedOrderRight.makerAddress, + compliantTakerAddress, + ]; + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); expect( newBalances[signedOrderLeft.makerAddress][defaultMakerAssetAddress], 'Checking left maker egress ERC20 account balance', - ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][defaultMakerAssetAddress].sub(expectedTransferAmounts.amountSoldByLeftMaker)); + ).to.be.bignumber.equal( + erc20Balances[signedOrderLeft.makerAddress][defaultMakerAssetAddress].sub( + expectedTransferAmounts.amountSoldByLeftMaker, + ), + ); expect( newBalances[signedOrderRight.makerAddress][defaultTakerAssetAddress], 'Checking right maker ingress ERC20 account balance', - ).to.be.bignumber.equal(erc20Balances[signedOrderRight.makerAddress][defaultTakerAssetAddress].sub(expectedTransferAmounts.amountSoldByRightMaker)); + ).to.be.bignumber.equal( + erc20Balances[signedOrderRight.makerAddress][defaultTakerAssetAddress].sub( + expectedTransferAmounts.amountSoldByRightMaker, + ), + ); expect( newBalances[compliantTakerAddress][defaultMakerAssetAddress], 'Checking taker ingress ERC20 account balance', - ).to.be.bignumber.equal(erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(expectedTransferAmounts.amountReceivedByTaker)); + ).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add( + expectedTransferAmounts.amountReceivedByTaker, + ), + ); expect( newBalances[signedOrderLeft.makerAddress][defaultTakerAssetAddress], 'Checking left maker ingress ERC20 account balance', - ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][defaultTakerAssetAddress].add(expectedTransferAmounts.amountBoughtByLeftMaker)); + ).to.be.bignumber.equal( + erc20Balances[signedOrderLeft.makerAddress][defaultTakerAssetAddress].add( + expectedTransferAmounts.amountBoughtByLeftMaker, + ), + ); expect( newBalances[signedOrderRight.makerAddress][defaultMakerAssetAddress], 'Checking right maker egress ERC20 account balance', ).to.be.bignumber.equal( - erc20Balances[signedOrderRight.makerAddress][defaultMakerAssetAddress].add(expectedTransferAmounts.amountBoughtByRightMaker), + erc20Balances[signedOrderRight.makerAddress][defaultMakerAssetAddress].add( + expectedTransferAmounts.amountBoughtByRightMaker, + ), ); // Paid fees expect( newBalances[signedOrderLeft.makerAddress][zrxToken.address], 'Checking left maker egress ERC20 account fees', - ).to.be.bignumber.equal(erc20Balances[signedOrderLeft.makerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByLeftMaker)); + ).to.be.bignumber.equal( + erc20Balances[signedOrderLeft.makerAddress][zrxToken.address].minus( + expectedTransferAmounts.feePaidByLeftMaker, + ), + ); expect( newBalances[signedOrderRight.makerAddress][zrxToken.address], 'Checking right maker egress ERC20 account fees', - ).to.be.bignumber.equal(erc20Balances[signedOrderRight.makerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByRightMaker)); + ).to.be.bignumber.equal( + erc20Balances[signedOrderRight.makerAddress][zrxToken.address].minus( + expectedTransferAmounts.feePaidByRightMaker, + ), + ); expect( newBalances[compliantTakerAddress][zrxToken.address], 'Checking taker egress ERC20 account fees', - ).to.be.bignumber.equal(erc20Balances[compliantTakerAddress][zrxToken.address].minus(expectedTransferAmounts.feePaidByTakerLeft).sub(expectedTransferAmounts.feePaidByTakerRight)); + ).to.be.bignumber.equal( + erc20Balances[compliantTakerAddress][zrxToken.address] + .minus(expectedTransferAmounts.feePaidByTakerLeft) + .sub(expectedTransferAmounts.feePaidByTakerRight), + ); // Received fees expect( newBalances[signedOrderLeft.feeRecipientAddress][zrxToken.address], 'Checking left fee recipient ingress ERC20 account fees', ).to.be.bignumber.equal( - erc20Balances[feeRecipientAddress][zrxToken.address].add(expectedTransferAmounts.feePaidByLeftMaker).add(expectedTransferAmounts.feePaidByRightMaker).add(expectedTransferAmounts.feePaidByTakerLeft).add(expectedTransferAmounts.feePaidByTakerRight), + erc20Balances[feeRecipientAddress][zrxToken.address] + .add(expectedTransferAmounts.feePaidByLeftMaker) + .add(expectedTransferAmounts.feePaidByRightMaker) + .add(expectedTransferAmounts.feePaidByTakerLeft) + .add(expectedTransferAmounts.feePaidByTakerRight), ); }); it('should revert if left maker does not meet the balance threshold', async () => { // Create signed order with non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.matchOrdersAsync( compliantSignedOrder, signedOrderWithBadMakerAddress, - compliantTakerAddress, + compliantTakerAddress, ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if right maker does not meet the balance threshold', async () => { // Create signed order with non-compliant maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress + makerAddress: nonCompliantAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.matchOrdersAsync( signedOrderWithBadMakerAddress, compliantSignedOrder, - compliantTakerAddress, + compliantTakerAddress, ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { @@ -1367,9 +1490,9 @@ describe.only(ContractName.BalanceThresholdFilter, () => { erc721NonCompliantBalanceThresholdWrapper.matchOrdersAsync( compliantSignedOrder, compliantSignedOrder, - nonCompliantAddress, + nonCompliantAddress, ), - RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold + RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); }); @@ -1382,30 +1505,44 @@ describe.only(ContractName.BalanceThresholdFilter, () => { }); it('Should successfully cancel order if maker meets balance threshold', async () => { // Verify order is not cancelled - const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( + compliantSignedOrder, + ); expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); // Cancel - const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrderAsync(compliantSignedOrder, compliantSignedOrder.makerAddress); + const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrderAsync( + compliantSignedOrder, + compliantSignedOrder.makerAddress, + ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( + compliantSignedOrder, + ); expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); }); it('Should successfully cancel order if maker does not meet balance threshold', async () => { // Create order where maker does not meet balance threshold const signedOrderWithBadMakerAddress = await nonCompliantOrderFactory.newSignedOrderAsync({}); // Verify order is not cancelled - const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(signedOrderWithBadMakerAddress) + const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + signedOrderWithBadMakerAddress, + ); expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); // Cancel - const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.cancelOrderAsync(signedOrderWithBadMakerAddress, signedOrderWithBadMakerAddress.makerAddress); + const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.cancelOrderAsync( + signedOrderWithBadMakerAddress, + signedOrderWithBadMakerAddress.makerAddress, + ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(signedOrderWithBadMakerAddress) + const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( + signedOrderWithBadMakerAddress, + ); expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); }); }); @@ -1420,20 +1557,27 @@ describe.only(ContractName.BalanceThresholdFilter, () => { await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync(), - ]; + ]; // Verify orders are not cancelled - await _.each(compliantSignedOrders, async (compliantSignedOrder) => { - const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + _.each(compliantSignedOrders, async signedOrder => { + const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( + signedOrder, + ); return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); }); // Cancel - const txReceipt = await erc721MakerBalanceThresholdWrapper.batchCancelOrdersAsync(compliantSignedOrders, compliantSignedOrder.makerAddress); + const txReceipt = await erc721MakerBalanceThresholdWrapper.batchCancelOrdersAsync( + compliantSignedOrders, + compliantSignedOrder.makerAddress, + ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - await _.each(compliantSignedOrders, async (compliantSignedOrder) => { - const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + _.each(compliantSignedOrders, async signedOrder => { + const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( + signedOrder, + ); return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); }); }); @@ -1443,20 +1587,27 @@ describe.only(ContractName.BalanceThresholdFilter, () => { await nonCompliantOrderFactory.newSignedOrderAsync(), await nonCompliantOrderFactory.newSignedOrderAsync(), await nonCompliantOrderFactory.newSignedOrderAsync(), - ]; + ]; // Verify orders are not cancelled - await _.each(nonCompliantSignedOrders, async (nonCompliantSignedOrder) => { - const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(nonCompliantSignedOrder) + _.each(nonCompliantSignedOrders, async signedOrder => { + const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + signedOrder, + ); return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); }); // Cancel - const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.batchCancelOrdersAsync(nonCompliantSignedOrders, nonCompliantAddress); + const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.batchCancelOrdersAsync( + nonCompliantSignedOrders, + nonCompliantAddress, + ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - await _.each(nonCompliantSignedOrders, async (nonCompliantSignedOrder) => { - const orderInfoAfterCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(nonCompliantSignedOrder) + _.each(nonCompliantSignedOrders, async signedOrder => { + const orderInfoAfterCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + signedOrder, + ); return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); }); }); @@ -1469,24 +1620,31 @@ describe.only(ContractName.BalanceThresholdFilter, () => { it('Should successfully batch cancel orders if maker meets balance threshold', async () => { // Create orders to cancel const compliantSignedOrders = [ - await orderFactory.newSignedOrderAsync({salt: new BigNumber(0)}), - await orderFactory.newSignedOrderAsync({salt: new BigNumber(1)}), - await orderFactory.newSignedOrderAsync({salt: new BigNumber(2)}), - ]; + await orderFactory.newSignedOrderAsync({ salt: new BigNumber(0) }), + await orderFactory.newSignedOrderAsync({ salt: new BigNumber(1) }), + await orderFactory.newSignedOrderAsync({ salt: new BigNumber(2) }), + ]; // Verify orders are not cancelled - await _.each(compliantSignedOrders, async (compliantSignedOrder) => { - const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + _.each(compliantSignedOrders, async signedOrder => { + const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( + signedOrder, + ); return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); }); // Cancel const cancelOrdersUpToThisSalt = new BigNumber(1); - const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrdersUpToAsync(cancelOrdersUpToThisSalt, compliantSignedOrder.makerAddress); + const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrdersUpToAsync( + cancelOrdersUpToThisSalt, + compliantSignedOrder.makerAddress, + ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - await _.each(compliantSignedOrders, async (compliantSignedOrder, salt: number) => { - const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync(compliantSignedOrder) + _.each(compliantSignedOrders, async (signedOrder, salt: number) => { + const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( + signedOrder, + ); const saltAsBigNumber = new BigNumber(salt); if (saltAsBigNumber.lessThanOrEqualTo(cancelOrdersUpToThisSalt)) { return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); @@ -1498,24 +1656,31 @@ describe.only(ContractName.BalanceThresholdFilter, () => { it('Should successfully batch cancel order if maker does not meet balance threshold', async () => { // Create orders to cancel const nonCompliantSignedOrders = [ - await nonCompliantOrderFactory.newSignedOrderAsync({salt: new BigNumber(0)}), - await nonCompliantOrderFactory.newSignedOrderAsync({salt: new BigNumber(1)}), - await nonCompliantOrderFactory.newSignedOrderAsync({salt: new BigNumber(2)}), - ]; + await nonCompliantOrderFactory.newSignedOrderAsync({ salt: new BigNumber(0) }), + await nonCompliantOrderFactory.newSignedOrderAsync({ salt: new BigNumber(1) }), + await nonCompliantOrderFactory.newSignedOrderAsync({ salt: new BigNumber(2) }), + ]; // Verify orders are not cancelled - await _.each(nonCompliantSignedOrders, async (nonCompliantSignedOrder) => { - const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(nonCompliantSignedOrder) + _.each(nonCompliantSignedOrders, async signedOrder => { + const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + signedOrder, + ); return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); }); // Cancel const cancelOrdersUpToThisSalt = new BigNumber(1); - const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.cancelOrdersUpToAsync(cancelOrdersUpToThisSalt, nonCompliantAddress); + const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.cancelOrdersUpToAsync( + cancelOrdersUpToThisSalt, + nonCompliantAddress, + ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; - assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); + await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - await _.each(nonCompliantSignedOrders, async (nonCompliantSignedOrder, salt: number) => { - const orderInfoAfterCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync(nonCompliantSignedOrder) + _.each(nonCompliantSignedOrders, async (signedOrder, salt: number) => { + const orderInfoAfterCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + signedOrder, + ); const saltAsBigNumber = new BigNumber(salt); if (saltAsBigNumber.lessThanOrEqualTo(cancelOrdersUpToThisSalt)) { return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); diff --git a/contracts/extensions/test/extensions/forwarder.ts b/contracts/extensions/test/extensions/forwarder.ts index a4afa283e..4027f493d 100644 --- a/contracts/extensions/test/extensions/forwarder.ts +++ b/contracts/extensions/test/extensions/forwarder.ts @@ -61,7 +61,6 @@ describe(ContractName.Forwarder, () => { let wethContract: WETH9Contract; let forwarderWrapper: ForwarderWrapper; let exchangeWrapper: ExchangeWrapper; - let takerPrivateKey: Buffer; let orderWithoutFee: SignedOrder; let orderWithFee: SignedOrder; diff --git a/contracts/extensions/test/utils/balance_threshold_wrapper.ts b/contracts/extensions/test/utils/balance_threshold_wrapper.ts index 63128686c..28a4ef011 100644 --- a/contracts/extensions/test/utils/balance_threshold_wrapper.ts +++ b/contracts/extensions/test/utils/balance_threshold_wrapper.ts @@ -1,16 +1,21 @@ +import { artifacts as protocolArtifacts, ExchangeContract } from '@0x/contracts-protocol'; +import { + FillResults, + formatters, + LogDecoder, + OrderInfo, + orderUtils, + TransactionFactory, +} from '@0x/contracts-test-utils'; +import { artifacts as tokensArtifacts } from '@0x/contracts-tokens'; import { SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import * as _ from 'lodash'; -import { ExchangeContract } from '@0x/contracts-protocol'; import { BalanceThresholdFilterContract } from '../../generated-wrappers/balance_threshold_filter'; - -import { formatters, LogDecoder, orderUtils, OrderInfo, TransactionFactory } from '@0x/contracts-test-utils'; import { artifacts } from '../../src/artifacts'; -import {artifacts as protocolArtifacts} from '@0x/contracts-protocol'; -import { artifacts as tokensArtifacts } from '@0x/contracts-tokens'; export class BalanceThresholdWrapper { private readonly _balanceThresholdFilter: BalanceThresholdFilterContract; @@ -18,12 +23,21 @@ export class BalanceThresholdWrapper { private readonly _exchange: ExchangeContract; private readonly _web3Wrapper: Web3Wrapper; private readonly _logDecoder: LogDecoder; - constructor(balanceThresholdFilter: BalanceThresholdFilterContract, exchangeContract: ExchangeContract, signerTransactionFactory: TransactionFactory, provider: Provider) { + constructor( + balanceThresholdFilter: BalanceThresholdFilterContract, + exchangeContract: ExchangeContract, + signerTransactionFactory: TransactionFactory, + provider: Provider, + ) { this._balanceThresholdFilter = balanceThresholdFilter; this._exchange = exchangeContract; this._signerTransactionFactory = signerTransactionFactory; this._web3Wrapper = new Web3Wrapper(provider); - this._logDecoder = new LogDecoder(this._web3Wrapper, {... artifacts, ... tokensArtifacts, ... protocolArtifacts} ); + this._logDecoder = new LogDecoder(this._web3Wrapper, { + ...artifacts, + ...tokensArtifacts, + ...protocolArtifacts, + }); } public async fillOrderAsync( signedOrder: SignedOrder, @@ -36,7 +50,7 @@ export class BalanceThresholdWrapper { params.takerAssetFillAmount, params.signature, ); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async fillOrKillOrderAsync( @@ -50,7 +64,7 @@ export class BalanceThresholdWrapper { params.takerAssetFillAmount, params.signature, ); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async fillOrderNoThrowAsync( @@ -64,7 +78,7 @@ export class BalanceThresholdWrapper { params.takerAssetFillAmount, params.signature, ); - const txReceipt = this._executeTransaction(data, from, opts.gas); + const txReceipt = this._executeTransactionAsync(data, from, opts.gas); return txReceipt; } public async batchFillOrdersAsync( @@ -78,7 +92,7 @@ export class BalanceThresholdWrapper { params.takerAssetFillAmounts, params.signatures, ); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async batchFillOrKillOrdersAsync( @@ -92,7 +106,7 @@ export class BalanceThresholdWrapper { params.takerAssetFillAmounts, params.signatures, ); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async batchFillOrdersNoThrowAsync( @@ -106,7 +120,7 @@ export class BalanceThresholdWrapper { params.takerAssetFillAmounts, params.signatures, ); - const txReceipt = this._executeTransaction(data, from, opts.gas); + const txReceipt = this._executeTransactionAsync(data, from, opts.gas); return txReceipt; } public async marketSellOrdersAsync( @@ -120,7 +134,7 @@ export class BalanceThresholdWrapper { params.takerAssetFillAmount, params.signatures, ); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async marketSellOrdersNoThrowAsync( @@ -134,7 +148,7 @@ export class BalanceThresholdWrapper { params.takerAssetFillAmount, params.signatures, ); - const txReceipt = this._executeTransaction(data, from, opts.gas); + const txReceipt = this._executeTransactionAsync(data, from, opts.gas); return txReceipt; } public async marketBuyOrdersAsync( @@ -148,7 +162,7 @@ export class BalanceThresholdWrapper { params.makerAssetFillAmount, params.signatures, ); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async marketBuyOrdersNoThrowAsync( @@ -162,13 +176,13 @@ export class BalanceThresholdWrapper { params.makerAssetFillAmount, params.signatures, ); - const txReceipt = this._executeTransaction(data, from, opts.gas); + const txReceipt = this._executeTransactionAsync(data, from, opts.gas); return txReceipt; } public async cancelOrderAsync(signedOrder: SignedOrder, from: string): Promise { const params = orderUtils.createCancel(signedOrder); const data = this._exchange.cancelOrder.getABIEncodedTransactionData(params.order); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async batchCancelOrdersAsync( @@ -177,12 +191,12 @@ export class BalanceThresholdWrapper { ): Promise { const params = formatters.createBatchCancel(orders); const data = this._exchange.batchCancelOrders.getABIEncodedTransactionData(params.orders); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async cancelOrdersUpToAsync(salt: BigNumber, from: string): Promise { const data = this._exchange.cancelOrdersUpTo.getABIEncodedTransactionData(salt); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise { @@ -198,7 +212,7 @@ export class BalanceThresholdWrapper { return orderEpoch; } public async getOrderInfoAsync(signedOrder: SignedOrder): Promise { - const orderInfo = (await this._exchange.getOrderInfo.callAsync(signedOrder)) as OrderInfo; + const orderInfo = await this._exchange.getOrderInfo.callAsync(signedOrder); return orderInfo; } public async getOrdersInfoAsync(signedOrders: SignedOrder[]): Promise { @@ -215,24 +229,47 @@ export class BalanceThresholdWrapper { params.left, params.right, params.leftSignature, - params.rightSignature + params.rightSignature, ); - const txReceipt = this._executeTransaction(data, from); + const txReceipt = this._executeTransactionAsync(data, from); return txReceipt; } + public async getFillOrderResultsAsync( + signedOrder: SignedOrder, + from: string, + opts: { takerAssetFillAmount?: BigNumber } = {}, + ): Promise { + const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount); + const fillResults = await this._exchange.fillOrder.callAsync( + params.order, + params.takerAssetFillAmount, + params.signature, + { from }, + ); + return fillResults; + } + public abiEncodeFillOrder(signedOrder: SignedOrder, opts: { takerAssetFillAmount?: BigNumber } = {}): string { + const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount); + const data = this._exchange.fillOrder.getABIEncodedTransactionData( + params.order, + params.takerAssetFillAmount, + params.signature, + ); + return data; + } public getBalanceThresholdAddress(): string { return this._balanceThresholdFilter.address; } public getExchangeAddress(): string { return this._exchange.address; } - // Exchange functions - //abiEncodeFillOrder - //getFillOrderResultsAsync - // - private async _executeTransaction(abiEncodedExchangeTxData: string, from: string, gas?: number): Promise { + private async _executeTransactionAsync( + abiEncodedExchangeTxData: string, + from: string, + gas?: number, + ): Promise { const signedExchangeTx = this._signerTransactionFactory.newSignedTransaction(abiEncodedExchangeTxData); - const txOpts = _.isUndefined(gas) ? {from} : {from, gas}; + const txOpts = _.isUndefined(gas) ? { from } : { from, gas }; const txHash = await this._balanceThresholdFilter.executeTransaction.sendTransactionAsync( signedExchangeTx.salt, signedExchangeTx.signerAddress, diff --git a/contracts/extensions/tsconfig.json b/contracts/extensions/tsconfig.json index 5d3ebfe74..a303e3f5c 100644 --- a/contracts/extensions/tsconfig.json +++ b/contracts/extensions/tsconfig.json @@ -6,6 +6,10 @@ "resolveJsonModule": true }, "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], - "files": ["./generated-artifacts/BalanceThresholdFilter.json", "./generated-artifacts/DutchAuction.json", "./generated-artifacts/Forwarder.json"], + "files": [ + "./generated-artifacts/BalanceThresholdFilter.json", + "./generated-artifacts/DutchAuction.json", + "./generated-artifacts/Forwarder.json" + ], "exclude": ["./deploy/solc/solc_bin"] } -- cgit v1.2.3 From fc684ad063151f160a5bc584482aabb56df71e00 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 11 Dec 2018 16:01:06 -0800 Subject: solhint fixes --- .../BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol | 8 ++++++-- .../BalanceThresholdFilter/interfaces/IThresholdAsset.sol | 3 ++- .../BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index 0ad8ccddf..51dbae8f3 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -53,7 +53,7 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { bytes signedExchangeTransaction, bytes signature ) - external + external { // Validate addresses. validateBalanceThresholdsOrRevert(); @@ -216,6 +216,7 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { // Step 2/2 Extract addresses to validate based on this selector. // See ../../utils/ExchangeSelectors/ExchangeSelectors.sol for selectors + // solhint-disable no-empty-blocks switch exchangeFunctionSelector case 0x297bb70b00000000000000000000000000000000000000000000000000000000 { recordAddressesForBatchFillVariant() } // batchFillOrders case 0x50dde19000000000000000000000000000000000000000000000000000000000 { recordAddressesForBatchFillVariant() } // batchFillOrdersNoThrow @@ -245,6 +246,7 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { // 64 -- strlen(INVALID_OR_BLOCKED_EXCHANGE_SELECTOR) rounded up to nearest 32-byte word. revert(0, 132) } + // solhint-enable no-empty-blocks ///// Validate Recorded Addresses ///// @@ -262,7 +264,9 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { // Validate addresses let thresholdAssetAddress := sload(THRESHOLD_ASSET_slot) let thresholdBalance := sload(THRESHOLD_BALANCE_slot) + // solhint-disable max-line-length for {let addressToValidate := addressesToValidateElementPtr} lt(addressToValidate, addressesToValidateElementEndPtr) {addressToValidate := add(addressToValidate, 0x20)} { + // solhint-enable max-line-length // Construct calldata for `THRESHOLD_ASSET.balanceOf` mstore(freeMemPtr, 0x70a0823100000000000000000000000000000000000000000000000000000000) mstore(add(freeMemPtr, 0x04), mload(addressToValidate)) @@ -316,4 +320,4 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { ///// If we hit this point then all addresses are valid ///// emit ValidatedAddresses(validatedAddresses); } -} \ No newline at end of file +} diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IThresholdAsset.sol b/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IThresholdAsset.sol index 61acaba0a..3e424b9f4 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IThresholdAsset.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IThresholdAsset.sol @@ -18,6 +18,7 @@ pragma solidity 0.4.24; + contract IThresholdAsset { /// @param _owner The address from which the balance will be retrieved @@ -27,4 +28,4 @@ contract IThresholdAsset { view returns (uint256); -} \ No newline at end of file +} diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol index ff0042f58..af7a9453b 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol @@ -26,6 +26,7 @@ import "../interfaces/IThresholdAsset.sol"; contract MBalanceThresholdFilterCore { // Points to 0x exchange contract + // solhint-disable var-name-mixedcase IExchange internal EXCHANGE; // The asset that must be held by makers/takers @@ -33,6 +34,7 @@ contract MBalanceThresholdFilterCore { // The minimum balance of `THRESHOLD_ASSET` that must be held by makers/takers uint256 internal THRESHOLD_BALANCE; + // solhint-enable var-name-mixedcase // Addresses that hold at least `THRESHOLD_BALANCE` of `THRESHOLD_ASSET` event ValidatedAddresses ( @@ -78,4 +80,4 @@ contract MBalanceThresholdFilterCore { /// If all addresses are valid then this function emits a ValidatedAddresses event, listing all /// of the addresses whose balance thresholds it checked. function validateBalanceThresholdsOrRevert() internal; -} \ No newline at end of file +} -- cgit v1.2.3 From dccca95c2c7a3bfcbf88db5f9182919f0e5ebf10 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 11 Dec 2018 16:02:45 -0800 Subject: removed `only` from tests --- contracts/extensions/test/extensions/balance_threshold_filter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts index e4eda3354..72227090b 100644 --- a/contracts/extensions/test/extensions/balance_threshold_filter.ts +++ b/contracts/extensions/test/extensions/balance_threshold_filter.ts @@ -46,7 +46,7 @@ interface ValidatedAddressesLog { args: { addresses: string[] }; } -describe.only(ContractName.BalanceThresholdFilter, () => { +describe(ContractName.BalanceThresholdFilter, () => { let compliantMakerAddress: string; let compliantMakerAddress2: string; let owner: string; -- cgit v1.2.3 From 34ff7fae9cffa7aaba5f0ba0060ed063a855f8e9 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 11 Dec 2018 16:07:19 -0800 Subject: Removed deprecated README + comments --- contracts/extensions/test/extensions/balance_threshold_filter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts index 72227090b..63cb9de31 100644 --- a/contracts/extensions/test/extensions/balance_threshold_filter.ts +++ b/contracts/extensions/test/extensions/balance_threshold_filter.ts @@ -135,7 +135,7 @@ describe(ContractName.BalanceThresholdFilter, () => { // Create proxies const erc20Proxy = await erc20Wrapper.deployProxyAsync(); await erc20Wrapper.setBalancesAndAllowancesAsync(); - // Deploy Exchange congtract + // Deploy Exchange contract exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync( protocolArtifacts.Exchange, provider, @@ -356,7 +356,6 @@ describe(ContractName.BalanceThresholdFilter, () => { ), ); }); - // @TODO - greater than 1 balance }); describe('batchFillOrders', () => { -- cgit v1.2.3 From a1266a3341cdc899a9090c90d6cf30b0ceb1db94 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 11 Dec 2018 16:36:56 -0800 Subject: Cleaned up tests for balance threshold filter --- .../test/extensions/balance_threshold_filter.ts | 1097 ++++++++++---------- 1 file changed, 534 insertions(+), 563 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts index 63cb9de31..ced9d6e25 100644 --- a/contracts/extensions/test/extensions/balance_threshold_filter.ts +++ b/contracts/extensions/test/extensions/balance_threshold_filter.ts @@ -46,13 +46,17 @@ interface ValidatedAddressesLog { args: { addresses: string[] }; } -describe(ContractName.BalanceThresholdFilter, () => { - let compliantMakerAddress: string; - let compliantMakerAddress2: string; +describe.only(ContractName.BalanceThresholdFilter, () => { + const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT); + const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT); + const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT); + + let validMakerAddress: string; + let validMakerAddress2: string; let owner: string; - let compliantTakerAddress: string; + let validTakerAddress: string; let feeRecipientAddress: string; - let nonCompliantAddress: string; + let invalidAddress: string; let defaultMakerAssetAddress: string; let defaultTakerAssetAddress: string; let zrxAssetData: string; @@ -62,27 +66,21 @@ describe(ContractName.BalanceThresholdFilter, () => { let orderFactory: OrderFactory; let orderFactory2: OrderFactory; - let nonCompliantOrderFactory: OrderFactory; + let invalidOrderFactory: OrderFactory; let erc20Wrapper: ERC20Wrapper; let erc20Balances: ERC20BalancesByOwner; let erc20TakerBalanceThresholdWrapper: BalanceThresholdWrapper; let erc721TakerBalanceThresholdWrapper: BalanceThresholdWrapper; let erc721MakerBalanceThresholdWrapper: BalanceThresholdWrapper; - let erc721NonCompliantBalanceThresholdWrapper: BalanceThresholdWrapper; - - let takerTransactionFactory: TransactionFactory; - let compliantSignedOrder: SignedOrder; - let compliantSignedOrder2: SignedOrder; - let compliantSignedFillOrderTx: SignedTransaction; + let erc721NonValidBalanceThresholdWrapper: BalanceThresholdWrapper; let defaultOrderParams: Partial; + let validSignedOrder: SignedOrder; + let validSignedOrder2: SignedOrder; + let validSignedFillOrderTx: SignedTransaction; - const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT); - const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT); - const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT); - - let erc721CompliantForwarderInstance: BalanceThresholdFilterContract; - let erc20CompliantForwarderInstance: BalanceThresholdFilterContract; + let erc721BalanceThresholdFilterInstance: BalanceThresholdFilterContract; + let erc20BalanceThresholdFilterInstance: BalanceThresholdFilterContract; const assertValidatedAddressesLog = async ( txReceipt: TransactionReceiptWithDecodedLogs, @@ -107,19 +105,23 @@ describe(ContractName.BalanceThresholdFilter, () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); const usedAddresses = ([ owner, - compliantMakerAddress, - compliantMakerAddress2, - compliantTakerAddress, + validMakerAddress, + validMakerAddress2, + validTakerAddress, feeRecipientAddress, - nonCompliantAddress, + invalidAddress, ] = accounts); + const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validTakerAddress)]; + const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validMakerAddress)]; + const secondMakerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validMakerAddress2)]; + const invalidAddressPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(invalidAddress)]; // Create wrappers erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); - const compliantAddresses = _.cloneDeepWith(usedAddresses); - _.remove(compliantAddresses, (address: string) => { - return address === nonCompliantAddress; + const validAddresses = _.cloneDeepWith(usedAddresses); + _.remove(validAddresses, (address: string) => { + return address === invalidAddress; }); - const erc721Wrapper = new ERC721Wrapper(provider, compliantAddresses, owner); + const erc721Wrapper = new ERC721Wrapper(provider, validAddresses, owner); // Deploy ERC20 tokens const numDummyErc20ToDeploy = 4; let erc20TokenA: DummyERC20TokenContract; @@ -148,12 +150,13 @@ describe(ContractName.BalanceThresholdFilter, () => { await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeInstance.address, { from: owner, }); - // Deploy Compliant Forwarder + // Deploy Balance Threshold Filters + // One uses an ERC721 token as its balance threshold asset; the other uses an ERC20 const erc721alanceThreshold = new BigNumber(1); await erc721Wrapper.deployProxyAsync(); const [erc721BalanceThresholdAsset] = await erc721Wrapper.deployDummyTokensAsync(); await erc721Wrapper.setBalancesAndAllowancesAsync(); - erc721CompliantForwarderInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync( + erc721BalanceThresholdFilterInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync( artifacts.BalanceThresholdFilter, provider, txDefaults, @@ -162,7 +165,7 @@ describe(ContractName.BalanceThresholdFilter, () => { erc721alanceThreshold, ); const erc20BalanceThreshold = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 10); - erc20CompliantForwarderInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync( + erc20BalanceThresholdFilterInstance = await BalanceThresholdFilterContract.deployFrom0xArtifactAsync( artifacts.BalanceThresholdFilter, provider, txDefaults, @@ -170,7 +173,6 @@ describe(ContractName.BalanceThresholdFilter, () => { erc20BalanceThresholdAsset.address, erc20BalanceThreshold, ); - // Default order parameters defaultOrderParams = { exchangeAddress: exchangeInstance.address, @@ -181,68 +183,51 @@ describe(ContractName.BalanceThresholdFilter, () => { takerAssetAmount, makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS_DEFAULT), takerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(150), DECIMALS_DEFAULT), - senderAddress: erc721CompliantForwarderInstance.address, + senderAddress: erc721BalanceThresholdFilterInstance.address, }; + // Create two order factories with valid makers (who meet the threshold balance), and + // one factory for an invalid address (that does not meet the threshold balance) + // Valid order factory #1 const defaultOrderParams1 = { - makerAddress: compliantMakerAddress, + makerAddress: validMakerAddress, ...defaultOrderParams, }; - const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantMakerAddress)]; - takerTransactionFactory = new TransactionFactory(makerPrivateKey, exchangeInstance.address); orderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams1); + // Valid order factory #2 const defaultOrderParams2 = { - makerAddress: compliantMakerAddress2, + makerAddress: validMakerAddress2, ...defaultOrderParams, }; - const secondMakerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantMakerAddress2)]; orderFactory2 = new OrderFactory(secondMakerPrivateKey, defaultOrderParams2); - - const nonCompliantPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(nonCompliantAddress)]; - const defaultNonCompliantOrderParams = { - makerAddress: nonCompliantAddress, + // Invalid order factory + const defaultNonValidOrderParams = { + makerAddress: invalidAddress, ...defaultOrderParams, }; - nonCompliantOrderFactory = new OrderFactory(nonCompliantPrivateKey, defaultNonCompliantOrderParams); - // Create Valid/Invalid orders - const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(compliantTakerAddress)]; - takerTransactionFactory = new TransactionFactory(takerPrivateKey, exchangeInstance.address); - compliantSignedOrder = await orderFactory.newSignedOrderAsync({ - senderAddress: erc721CompliantForwarderInstance.address, - }); - const compliantSignedOrderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress( - compliantSignedOrder, - ); - const compliantSignedOrderWithoutExchangeAddressData = exchangeInstance.fillOrder.getABIEncodedTransactionData( - compliantSignedOrderWithoutExchangeAddress, - takerAssetFillAmount, - compliantSignedOrder.signature, - ); - compliantSignedFillOrderTx = takerTransactionFactory.newSignedTransaction( - compliantSignedOrderWithoutExchangeAddressData, - ); - + invalidOrderFactory = new OrderFactory(invalidAddressPrivateKey, defaultNonValidOrderParams); + // Create Balance Thresold Wrappers erc20TakerBalanceThresholdWrapper = new BalanceThresholdWrapper( - erc20CompliantForwarderInstance, + erc20BalanceThresholdFilterInstance, exchangeInstance, new TransactionFactory(takerPrivateKey, exchangeInstance.address), provider, ); erc721TakerBalanceThresholdWrapper = new BalanceThresholdWrapper( - erc721CompliantForwarderInstance, + erc721BalanceThresholdFilterInstance, exchangeInstance, new TransactionFactory(takerPrivateKey, exchangeInstance.address), provider, ); erc721MakerBalanceThresholdWrapper = new BalanceThresholdWrapper( - erc721CompliantForwarderInstance, + erc721BalanceThresholdFilterInstance, exchangeInstance, new TransactionFactory(makerPrivateKey, exchangeInstance.address), provider, ); - erc721NonCompliantBalanceThresholdWrapper = new BalanceThresholdWrapper( - erc721CompliantForwarderInstance, + erc721NonValidBalanceThresholdWrapper = new BalanceThresholdWrapper( + erc721BalanceThresholdFilterInstance, exchangeInstance, - new TransactionFactory(nonCompliantPrivateKey, exchangeInstance.address), + new TransactionFactory(invalidAddressPrivateKey, exchangeInstance.address), provider, ); }); @@ -256,104 +241,90 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('General Sanity Checks', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both maker/taker when both maker and taker exceed the balance threshold of an ERC20 token', async () => { - const compliantSignedOrderERC20Sender = await orderFactory.newSignedOrderAsync({ + const validSignedOrderERC20Sender = await orderFactory.newSignedOrderAsync({ ...defaultOrderParams, - makerAddress: compliantMakerAddress, + makerAddress: validMakerAddress, senderAddress: erc20TakerBalanceThresholdWrapper.getBalanceThresholdAddress(), }); // Execute a valid fill const txReceipt = await erc20TakerBalanceThresholdWrapper.fillOrderAsync( - compliantSignedOrderERC20Sender, - compliantTakerAddress, + validSignedOrderERC20Sender, + validTakerAddress, { takerAssetFillAmount }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid = compliantSignedOrder.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid = validSignedOrder.makerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid), ); - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)), ); }); - it('should revert if the signed transaction is not intended for supported', async () => { + it('should revert if the Exchange transaction function is not supported', async () => { // Create signed order without the fillOrder function selector - const txDataBuf = ethUtil.toBuffer(compliantSignedFillOrderTx.data); - const selectorLengthInBytes = 4; - const txDataBufMinusSelector = txDataBuf.slice(selectorLengthInBytes); - const badSelector = '0x00000000'; - const badSelectorBuf = ethUtil.toBuffer(badSelector); - const txDataBufWithBadSelector = Buffer.concat([badSelectorBuf, txDataBufMinusSelector]); - const txDataBufWithBadSelectorHex = ethUtil.bufferToHex(txDataBufWithBadSelector); - // Call compliant forwarder - return expectTransactionFailedWithoutReasonAsync( - erc721CompliantForwarderInstance.executeTransaction.sendTransactionAsync( - compliantSignedFillOrderTx.salt, - compliantSignedFillOrderTx.signerAddress, - txDataBufWithBadSelectorHex, - compliantSignedFillOrderTx.signature, + const salt = new BigNumber(0); + const badSelectorHex = '0x00000000'; + const signatureHex = '0x'; + // Call valid forwarder + return expectTransactionFailedAsync( + erc721BalanceThresholdFilterInstance.executeTransaction.sendTransactionAsync( + salt, + validTakerAddress, + badSelectorHex, + signatureHex, ), + RevertReason.InvalidOrBlockedExchangeSelector ); }); - it('should revert if senderAddress is not set to the compliant forwarding contract', async () => { + it('should revert if senderAddress is not set to the valid forwarding contract', async () => { // Create signed order with incorrect senderAddress const notBalanceThresholdFilterAddress = zrxToken.address; const signedOrderWithBadSenderAddress = await orderFactory.newSignedOrderAsync({ senderAddress: notBalanceThresholdFilterAddress, }); - const signedOrderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress( - signedOrderWithBadSenderAddress, - ); - const signedOrderWithoutExchangeAddressData = exchangeInstance.fillOrder.getABIEncodedTransactionData( - signedOrderWithoutExchangeAddress, - takerAssetFillAmount, - compliantSignedOrder.signature, - ); - const signedFillOrderTx = takerTransactionFactory.newSignedTransaction( - signedOrderWithoutExchangeAddressData, - ); - // Call compliant forwarder - return expectTransactionFailedWithoutReasonAsync( - erc721CompliantForwarderInstance.executeTransaction.sendTransactionAsync( - signedFillOrderTx.salt, - signedFillOrderTx.signerAddress, - signedFillOrderTx.data, - signedFillOrderTx.signature, + // Call valid forwarder + return expectTransactionFailedAsync( + erc721TakerBalanceThresholdWrapper.fillOrderAsync( + signedOrderWithBadSenderAddress, + validTakerAddress, + { takerAssetFillAmount }, ), + RevertReason.FailedExecution ); }); }); @@ -361,68 +332,68 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('batchFillOrders', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both makers/taker when both maker and taker meet the balance threshold', async () => { // Execute a valid fill - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync( orders, - compliantTakerAddress, + validTakerAddress, { takerAssetFillAmounts }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedOrder2.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validSignedOrder2.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); const makerAssetFillAmount = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid = compliantSignedOrder.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid = validSignedOrder.makerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.makerAssetAmount) .times(2); // Maker #1 - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid), ); // Maker #2 - expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid), ); // Taker - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( @@ -430,25 +401,25 @@ describe(ContractName.BalanceThresholdFilter, () => { ); }); it('should revert if one maker does not meet the balance threshold', async () => { - // Create order set with one non-compliant maker address + // Create order set with one non-valid maker address const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress, + makerAddress: invalidAddress, }); - const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + const orders = [validSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync(orders, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync(orders, validTakerAddress, { takerAssetFillAmounts, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.batchFillOrdersAsync(orders, nonCompliantAddress, { + erc721NonValidBalanceThresholdWrapper.batchFillOrdersAsync(orders, invalidAddress, { takerAssetFillAmounts, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -459,68 +430,68 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('batchFillOrdersNoThrow', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both makers/taker when both maker and taker meet the balance threshold', async () => { // Execute a valid fill - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync( orders, - compliantTakerAddress, + validTakerAddress, { takerAssetFillAmounts }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedOrder2.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validSignedOrder2.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); const makerAssetFillAmount = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid = compliantSignedOrder.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid = validSignedOrder.makerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.makerAssetAmount) .times(2); // Maker #1 - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid), ); // Maker #2 - expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid), ); // Taker - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( @@ -528,25 +499,25 @@ describe(ContractName.BalanceThresholdFilter, () => { ); }); it('should revert if one maker does not meet the balance threshold', async () => { - // Create order set with one non-compliant maker address + // Create order set with one non-valid maker address const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress, + makerAddress: invalidAddress, }); - const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + const orders = [validSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, validTakerAddress, { takerAssetFillAmounts, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, nonCompliantAddress, { + erc721NonValidBalanceThresholdWrapper.batchFillOrdersNoThrowAsync(orders, invalidAddress, { takerAssetFillAmounts, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -557,68 +528,68 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('batchFillOrKillOrders', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { // Execute a valid fill - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync( orders, - compliantTakerAddress, + validTakerAddress, { takerAssetFillAmounts }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedOrder2.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validSignedOrder2.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const cumulativeTakerAssetFillAmount = takerAssetFillAmount.times(2); const makerAssetFillAmount = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid = compliantSignedOrder.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid = validSignedOrder.makerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.makerAssetAmount) .times(2); // Maker #1 - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid), ); // Maker #2 - expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid), ); // Taker - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount.times(2)), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( @@ -626,36 +597,36 @@ describe(ContractName.BalanceThresholdFilter, () => { ); }); it('should revert if one maker does not meet the balance threshold', async () => { - // Create order set with one non-compliant maker address + // Create order set with one non-valid maker address const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress, + makerAddress: invalidAddress, }); - const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + const orders = [validSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, validTakerAddress, { takerAssetFillAmounts, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, nonCompliantAddress, { + erc721NonValidBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, invalidAddress, { takerAssetFillAmounts, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if one takerAssetFillAmount is not fully filled', async () => { - const tooBigTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.times(2); - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const tooBigTakerAssetFillAmount = validSignedOrder.takerAssetAmount.times(2); + const orders = [validSignedOrder, validSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, tooBigTakerAssetFillAmount]; return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.batchFillOrKillOrdersAsync(orders, validTakerAddress, { takerAssetFillAmounts, }), RevertReason.FailedExecution, @@ -666,65 +637,65 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('fillOrder', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { // Execute a valid fill const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderAsync( - compliantSignedOrder, - compliantTakerAddress, + validSignedOrder, + validTakerAddress, { takerAssetFillAmount }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid = compliantSignedOrder.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid = validSignedOrder.makerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid), ); - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)), ); }); it('should revert if maker does not meet the balance threshold', async () => { - // Create signed order with non-compliant maker address + // Create signed order with non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress, + senderAddress: erc721BalanceThresholdFilterInstance.address, + makerAddress: invalidAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.fillOrderAsync( signedOrderWithBadMakerAddress, - compliantTakerAddress, + validTakerAddress, { takerAssetFillAmount }, ), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -732,7 +703,7 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.fillOrderAsync(compliantSignedOrder, nonCompliantAddress, { + erc721NonValidBalanceThresholdWrapper.fillOrderAsync(validSignedOrder, invalidAddress, { takerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -743,65 +714,65 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('fillOrderNoThrow', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { // Execute a valid fill const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync( - compliantSignedOrder, - compliantTakerAddress, + validSignedOrder, + validTakerAddress, { takerAssetFillAmount }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid = compliantSignedOrder.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid = validSignedOrder.makerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid), ); - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)), ); }); it('should revert if maker does not meet the balance threshold', async () => { - // Create signed order with non-compliant maker address + // Create signed order with non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress, + senderAddress: erc721BalanceThresholdFilterInstance.address, + makerAddress: invalidAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync( signedOrderWithBadMakerAddress, - compliantTakerAddress, + validTakerAddress, { takerAssetFillAmount }, ), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -809,9 +780,9 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.fillOrderNoThrowAsync( - compliantSignedOrder, - nonCompliantAddress, + erc721NonValidBalanceThresholdWrapper.fillOrderNoThrowAsync( + validSignedOrder, + invalidAddress, { takerAssetFillAmount }, ), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -822,66 +793,66 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('fillOrKillOrder', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both maker/taker when both maker and taker meet the balance threshold', async () => { // Execute a valid fill - const takerAssetFillAmount_ = compliantSignedOrder.takerAssetAmount; + const takerAssetFillAmount_ = validSignedOrder.takerAssetAmount; const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync( - compliantSignedOrder, - compliantTakerAddress, + validSignedOrder, + validTakerAddress, { takerAssetFillAmount: takerAssetFillAmount_ }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount = takerAssetFillAmount_ - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid = compliantSignedOrder.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid = validSignedOrder.makerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee .times(makerAssetFillAmount) - .dividedToIntegerBy(compliantSignedOrder.makerAssetAmount); - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), + .dividedToIntegerBy(validSignedOrder.makerAssetAmount); + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(makerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount_), + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(takerAssetFillAmount_), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(makerFeePaid), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(makerFeePaid), ); - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount_), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(takerAssetFillAmount_), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(makerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)), ); }); it('should revert if maker does not meet the balance threshold', async () => { - // Create signed order with non-compliant maker address + // Create signed order with non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress, + senderAddress: erc721BalanceThresholdFilterInstance.address, + makerAddress: invalidAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync( signedOrderWithBadMakerAddress, - compliantTakerAddress, + validTakerAddress, { takerAssetFillAmount }, ), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -889,18 +860,18 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.fillOrKillOrderAsync( - compliantSignedOrder, - nonCompliantAddress, + erc721NonValidBalanceThresholdWrapper.fillOrKillOrderAsync( + validSignedOrder, + invalidAddress, { takerAssetFillAmount }, ), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if takerAssetFillAmount is not fully filled', async () => { - const tooBigTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.times(2); + const tooBigTakerAssetFillAmount = validSignedOrder.takerAssetAmount.times(2); return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync(compliantSignedOrder, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.fillOrKillOrderAsync(validSignedOrder, validTakerAddress, { takerAssetFillAmount: tooBigTakerAssetFillAmount, }), RevertReason.FailedExecution, @@ -911,98 +882,98 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('marketSellOrders', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { // Execute a valid fill - const orders = [compliantSignedOrder, compliantSignedOrder2]; - const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); + const orders = [validSignedOrder, validSignedOrder2]; + const cumulativeTakerAssetFillAmount = validSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync( orders, - compliantTakerAddress, + validTakerAddress, { takerAssetFillAmount: cumulativeTakerAssetFillAmount }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedOrder2.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validSignedOrder2.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount2 = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid2 = compliantSignedOrder2.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid2 = validSignedOrder2.makerFee .times(makerAssetFillAmount2) - .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); - const takerFeePaid2 = compliantSignedOrder2.takerFee + .dividedToIntegerBy(validSignedOrder2.makerAssetAmount); + const takerFeePaid2 = validSignedOrder2.takerFee .times(makerAssetFillAmount2) - .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); - const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); + .dividedToIntegerBy(validSignedOrder2.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2); + const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); // Maker #1 - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus( - compliantSignedOrder.makerAssetAmount, + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus( + validSignedOrder.makerAssetAmount, ), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add( - compliantSignedOrder.takerAssetAmount, + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add( + validSignedOrder.takerAssetAmount, ), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee), ); // Maker #2 - expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), + expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), ); - expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), + expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid2), ); // Taker - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[feeRecipientAddress][zrxToken.address] - .add(compliantSignedOrder.makerFee) + .add(validSignedOrder.makerFee) .add(makerFeePaid2) .add(takerFeePaid), ); }); it('should revert if one maker does not meet the balance threshold', async () => { - // Create order set with one non-compliant maker address + // Create order set with one non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress, + makerAddress: invalidAddress, }); - const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + const orders = [validSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync(orders, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.marketSellOrdersAsync(orders, validTakerAddress, { takerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.marketSellOrdersAsync(orders, nonCompliantAddress, { + erc721NonValidBalanceThresholdWrapper.marketSellOrdersAsync(orders, invalidAddress, { takerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -1013,98 +984,98 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('marketSellOrdersNoThrow', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { // Execute a valid fill - const orders = [compliantSignedOrder, compliantSignedOrder2]; - const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); + const orders = [validSignedOrder, validSignedOrder2]; + const cumulativeTakerAssetFillAmount = validSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync( orders, - compliantTakerAddress, + validTakerAddress, { takerAssetFillAmount: cumulativeTakerAssetFillAmount }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedOrder2.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validSignedOrder2.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); const makerAssetFillAmount2 = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const makerFeePaid2 = compliantSignedOrder2.makerFee + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const makerFeePaid2 = validSignedOrder2.makerFee .times(makerAssetFillAmount2) - .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); - const takerFeePaid2 = compliantSignedOrder2.takerFee + .dividedToIntegerBy(validSignedOrder2.makerAssetAmount); + const takerFeePaid2 = validSignedOrder2.takerFee .times(makerAssetFillAmount2) - .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); - const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); + .dividedToIntegerBy(validSignedOrder2.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2); + const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); // Maker #1 - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus( - compliantSignedOrder.makerAssetAmount, + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus( + validSignedOrder.makerAssetAmount, ), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add( - compliantSignedOrder.takerAssetAmount, + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add( + validSignedOrder.takerAssetAmount, ), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee), ); // Maker #2 - expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), + expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), ); - expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), + expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid2), ); // Taker - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[feeRecipientAddress][zrxToken.address] - .add(compliantSignedOrder.makerFee) + .add(validSignedOrder.makerFee) .add(makerFeePaid2) .add(takerFeePaid), ); }); it('should revert if one maker does not meet the balance threshold', async () => { - // Create order set with one non-compliant maker address + // Create order set with one non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress, + makerAddress: invalidAddress, }); - const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + const orders = [validSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, validTakerAddress, { takerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, nonCompliantAddress, { + erc721NonValidBalanceThresholdWrapper.marketSellOrdersNoThrowAsync(orders, invalidAddress, { takerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -1115,100 +1086,100 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('marketBuyOrders', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { // Execute a valid fill - const orders = [compliantSignedOrder, compliantSignedOrder2]; - const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); + const orders = [validSignedOrder, validSignedOrder2]; + const cumulativeTakerAssetFillAmount = validSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); const makerAssetFillAmount2 = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync( orders, - compliantTakerAddress, + validTakerAddress, { makerAssetFillAmount: cumulativeMakerAssetFillAmount }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedOrder2.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validSignedOrder2.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); - const makerFeePaid2 = compliantSignedOrder2.makerFee + const makerFeePaid2 = validSignedOrder2.makerFee .times(makerAssetFillAmount2) - .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); - const takerFeePaid2 = compliantSignedOrder2.takerFee + .dividedToIntegerBy(validSignedOrder2.makerAssetAmount); + const takerFeePaid2 = validSignedOrder2.takerFee .times(makerAssetFillAmount2) - .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); + .dividedToIntegerBy(validSignedOrder2.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2); // Maker #1 - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus( - compliantSignedOrder.makerAssetAmount, + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus( + validSignedOrder.makerAssetAmount, ), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add( - compliantSignedOrder.takerAssetAmount, + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add( + validSignedOrder.takerAssetAmount, ), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee), ); // Maker #2 - expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), + expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), ); - expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), + expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid2), ); // Taker - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[feeRecipientAddress][zrxToken.address] - .add(compliantSignedOrder.makerFee) + .add(validSignedOrder.makerFee) .add(makerFeePaid2) .add(takerFeePaid), ); }); it('should revert if one maker does not meet the balance threshold', async () => { - // Create order set with one non-compliant maker address + // Create order set with one non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress, + makerAddress: invalidAddress, }); - const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + const orders = [validSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction const dummyMakerAssetFillAmount = new BigNumber(0); return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync(orders, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync(orders, validTakerAddress, { makerAssetFillAmount: dummyMakerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; const dummyMakerAssetFillAmount = new BigNumber(0); return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.marketBuyOrdersAsync(orders, nonCompliantAddress, { + erc721NonValidBalanceThresholdWrapper.marketBuyOrdersAsync(orders, invalidAddress, { makerAssetFillAmount: dummyMakerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -1219,100 +1190,100 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('marketBuyOrdersNoThrowAsync', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('should transfer the correct amounts and validate both makers/taker when both makers and taker meet the balance threshold', async () => { // Execute a valid fill - const orders = [compliantSignedOrder, compliantSignedOrder2]; - const cumulativeTakerAssetFillAmount = compliantSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); + const orders = [validSignedOrder, validSignedOrder2]; + const cumulativeTakerAssetFillAmount = validSignedOrder.takerAssetAmount.plus(takerAssetFillAmount); const makerAssetFillAmount2 = takerAssetFillAmount - .times(compliantSignedOrder.makerAssetAmount) - .dividedToIntegerBy(compliantSignedOrder.takerAssetAmount); - const cumulativeMakerAssetFillAmount = compliantSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); + .times(validSignedOrder.makerAssetAmount) + .dividedToIntegerBy(validSignedOrder.takerAssetAmount); + const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync( orders, - compliantTakerAddress, + validTakerAddress, { makerAssetFillAmount: cumulativeMakerAssetFillAmount }, ); // Assert validated addresses const expectedValidatedAddresseses = [ - compliantSignedOrder.makerAddress, - compliantSignedOrder2.makerAddress, - compliantSignedFillOrderTx.signerAddress, + validSignedOrder.makerAddress, + validSignedOrder2.makerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); - const makerFeePaid2 = compliantSignedOrder2.makerFee + const makerFeePaid2 = validSignedOrder2.makerFee .times(makerAssetFillAmount2) - .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); - const takerFeePaid2 = compliantSignedOrder2.takerFee + .dividedToIntegerBy(validSignedOrder2.makerAssetAmount); + const takerFeePaid2 = validSignedOrder2.takerFee .times(makerAssetFillAmount2) - .dividedToIntegerBy(compliantSignedOrder2.makerAssetAmount); - const takerFeePaid = compliantSignedOrder.takerFee.plus(takerFeePaid2); + .dividedToIntegerBy(validSignedOrder2.makerAssetAmount); + const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2); // Maker #1 - expect(newBalances[compliantMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultMakerAssetAddress].minus( - compliantSignedOrder.makerAssetAmount, + expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus( + validSignedOrder.makerAssetAmount, ), ); - expect(newBalances[compliantMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][defaultTakerAssetAddress].add( - compliantSignedOrder.takerAssetAmount, + expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add( + validSignedOrder.takerAssetAmount, ), ); - expect(newBalances[compliantMakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress][zrxToken.address].minus(compliantSignedOrder.makerFee), + expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee), ); // Maker #2 - expect(newBalances[compliantMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), + expect(newBalances[validMakerAddress2][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultMakerAssetAddress].minus(makerAssetFillAmount2), ); - expect(newBalances[compliantMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), + expect(newBalances[validMakerAddress2][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][defaultTakerAssetAddress].add(takerAssetFillAmount), ); - expect(newBalances[compliantMakerAddress2][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantMakerAddress2][zrxToken.address].minus(makerFeePaid2), + expect(newBalances[validMakerAddress2][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validMakerAddress2][zrxToken.address].minus(makerFeePaid2), ); // Taker - expect(newBalances[compliantTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultTakerAssetAddress].minus(cumulativeTakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), + expect(newBalances[validTakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add(cumulativeMakerAssetFillAmount), ); - expect(newBalances[compliantTakerAddress][zrxToken.address]).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address].minus(takerFeePaid), + expect(newBalances[validTakerAddress][zrxToken.address]).to.be.bignumber.equal( + erc20Balances[validTakerAddress][zrxToken.address].minus(takerFeePaid), ); // Fee recipient expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[feeRecipientAddress][zrxToken.address] - .add(compliantSignedOrder.makerFee) + .add(validSignedOrder.makerFee) .add(makerFeePaid2) .add(takerFeePaid), ); }); it('should revert if one maker does not meet the balance threshold', async () => { - // Create order set with one non-compliant maker address + // Create order set with one non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - makerAddress: nonCompliantAddress, + makerAddress: invalidAddress, }); - const orders = [compliantSignedOrder, signedOrderWithBadMakerAddress]; + const orders = [validSignedOrder, signedOrderWithBadMakerAddress]; // Execute transaction const dummyMakerAssetFillAmount = new BigNumber(0); return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, compliantTakerAddress, { + erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, validTakerAddress, { makerAssetFillAmount: dummyMakerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { - const orders = [compliantSignedOrder, compliantSignedOrder2]; + const orders = [validSignedOrder, validSignedOrder2]; const dummyMakerAssetFillAmount = new BigNumber(0); return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, nonCompliantAddress, { + erc721NonValidBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync(orders, invalidAddress, { makerAssetFillAmount: dummyMakerAssetFillAmount, }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, @@ -1323,8 +1294,8 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('matchOrders', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('Should transfer correct amounts when both makers and taker meet the balance threshold', async () => { // Test values/results taken from Match Orders test: @@ -1364,13 +1335,13 @@ describe(ContractName.BalanceThresholdFilter, () => { const txReceipt = await erc721TakerBalanceThresholdWrapper.matchOrdersAsync( signedOrderLeft, signedOrderRight, - compliantTakerAddress, + validTakerAddress, ); // Assert validated addresses const expectedValidatedAddresseses = [ signedOrderLeft.makerAddress, signedOrderRight.makerAddress, - compliantTakerAddress, + validTakerAddress, ]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances @@ -1392,10 +1363,10 @@ describe(ContractName.BalanceThresholdFilter, () => { ), ); expect( - newBalances[compliantTakerAddress][defaultMakerAssetAddress], + newBalances[validTakerAddress][defaultMakerAssetAddress], 'Checking taker ingress ERC20 account balance', ).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][defaultMakerAssetAddress].add( + erc20Balances[validTakerAddress][defaultMakerAssetAddress].add( expectedTransferAmounts.amountReceivedByTaker, ), ); @@ -1433,10 +1404,10 @@ describe(ContractName.BalanceThresholdFilter, () => { ), ); expect( - newBalances[compliantTakerAddress][zrxToken.address], + newBalances[validTakerAddress][zrxToken.address], 'Checking taker egress ERC20 account fees', ).to.be.bignumber.equal( - erc20Balances[compliantTakerAddress][zrxToken.address] + erc20Balances[validTakerAddress][zrxToken.address] .minus(expectedTransferAmounts.feePaidByTakerLeft) .sub(expectedTransferAmounts.feePaidByTakerRight), ); @@ -1453,43 +1424,43 @@ describe(ContractName.BalanceThresholdFilter, () => { ); }); it('should revert if left maker does not meet the balance threshold', async () => { - // Create signed order with non-compliant maker address + // Create signed order with non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress, + senderAddress: erc721BalanceThresholdFilterInstance.address, + makerAddress: invalidAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.matchOrdersAsync( - compliantSignedOrder, + validSignedOrder, signedOrderWithBadMakerAddress, - compliantTakerAddress, + validTakerAddress, ), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if right maker does not meet the balance threshold', async () => { - // Create signed order with non-compliant maker address + // Create signed order with non-valid maker address const signedOrderWithBadMakerAddress = await orderFactory.newSignedOrderAsync({ - senderAddress: erc721CompliantForwarderInstance.address, - makerAddress: nonCompliantAddress, + senderAddress: erc721BalanceThresholdFilterInstance.address, + makerAddress: invalidAddress, }); // Execute transaction return expectTransactionFailedAsync( erc721TakerBalanceThresholdWrapper.matchOrdersAsync( signedOrderWithBadMakerAddress, - compliantSignedOrder, - compliantTakerAddress, + validSignedOrder, + validTakerAddress, ), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( - erc721NonCompliantBalanceThresholdWrapper.matchOrdersAsync( - compliantSignedOrder, - compliantSignedOrder, - nonCompliantAddress, + erc721NonValidBalanceThresholdWrapper.matchOrdersAsync( + validSignedOrder, + validSignedOrder, + invalidAddress, ), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); @@ -1499,39 +1470,39 @@ describe(ContractName.BalanceThresholdFilter, () => { describe('cancelOrder', () => { beforeEach(async () => { erc20Balances = await erc20Wrapper.getBalancesAsync(); - compliantSignedOrder = await orderFactory.newSignedOrderAsync(); - compliantSignedOrder2 = await orderFactory2.newSignedOrderAsync(); + validSignedOrder = await orderFactory.newSignedOrderAsync(); + validSignedOrder2 = await orderFactory2.newSignedOrderAsync(); }); it('Should successfully cancel order if maker meets balance threshold', async () => { // Verify order is not cancelled const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( - compliantSignedOrder, + validSignedOrder, ); expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); // Cancel const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrderAsync( - compliantSignedOrder, - compliantSignedOrder.makerAddress, + validSignedOrder, + validSignedOrder.makerAddress, ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( - compliantSignedOrder, + validSignedOrder, ); expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); }); it('Should successfully cancel order if maker does not meet balance threshold', async () => { // Create order where maker does not meet balance threshold - const signedOrderWithBadMakerAddress = await nonCompliantOrderFactory.newSignedOrderAsync({}); + const signedOrderWithBadMakerAddress = await invalidOrderFactory.newSignedOrderAsync({}); // Verify order is not cancelled - const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + const orderInfoBeforeCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync( signedOrderWithBadMakerAddress, ); expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); // Cancel - const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.cancelOrderAsync( + const txReceipt = await erc721NonValidBalanceThresholdWrapper.cancelOrderAsync( signedOrderWithBadMakerAddress, signedOrderWithBadMakerAddress.makerAddress, ); @@ -1552,13 +1523,13 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('Should successfully batch cancel orders if maker meets balance threshold', async () => { // Create orders to cancel - const compliantSignedOrders = [ + const validSignedOrders = [ await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync(), await orderFactory.newSignedOrderAsync(), ]; // Verify orders are not cancelled - _.each(compliantSignedOrders, async signedOrder => { + _.each(validSignedOrders, async signedOrder => { const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( signedOrder, ); @@ -1566,14 +1537,14 @@ describe(ContractName.BalanceThresholdFilter, () => { }); // Cancel const txReceipt = await erc721MakerBalanceThresholdWrapper.batchCancelOrdersAsync( - compliantSignedOrders, - compliantSignedOrder.makerAddress, + validSignedOrders, + validSignedOrder.makerAddress, ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - _.each(compliantSignedOrders, async signedOrder => { + _.each(validSignedOrders, async signedOrder => { const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( signedOrder, ); @@ -1582,29 +1553,29 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('Should successfully batch cancel order if maker does not meet balance threshold', async () => { // Create orders to cancel - const nonCompliantSignedOrders = [ - await nonCompliantOrderFactory.newSignedOrderAsync(), - await nonCompliantOrderFactory.newSignedOrderAsync(), - await nonCompliantOrderFactory.newSignedOrderAsync(), + const invalidSignedOrders = [ + await invalidOrderFactory.newSignedOrderAsync(), + await invalidOrderFactory.newSignedOrderAsync(), + await invalidOrderFactory.newSignedOrderAsync(), ]; // Verify orders are not cancelled - _.each(nonCompliantSignedOrders, async signedOrder => { - const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + _.each(invalidSignedOrders, async signedOrder => { + const orderInfoBeforeCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync( signedOrder, ); return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); }); // Cancel - const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.batchCancelOrdersAsync( - nonCompliantSignedOrders, - nonCompliantAddress, + const txReceipt = await erc721NonValidBalanceThresholdWrapper.batchCancelOrdersAsync( + invalidSignedOrders, + invalidAddress, ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - _.each(nonCompliantSignedOrders, async signedOrder => { - const orderInfoAfterCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + _.each(invalidSignedOrders, async signedOrder => { + const orderInfoAfterCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync( signedOrder, ); return expect(orderInfoAfterCancelling.orderStatus).to.be.equal(OrderStatus.CANCELLED); @@ -1618,13 +1589,13 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('Should successfully batch cancel orders if maker meets balance threshold', async () => { // Create orders to cancel - const compliantSignedOrders = [ + const validSignedOrders = [ await orderFactory.newSignedOrderAsync({ salt: new BigNumber(0) }), await orderFactory.newSignedOrderAsync({ salt: new BigNumber(1) }), await orderFactory.newSignedOrderAsync({ salt: new BigNumber(2) }), ]; // Verify orders are not cancelled - _.each(compliantSignedOrders, async signedOrder => { + _.each(validSignedOrders, async signedOrder => { const orderInfoBeforeCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( signedOrder, ); @@ -1634,13 +1605,13 @@ describe(ContractName.BalanceThresholdFilter, () => { const cancelOrdersUpToThisSalt = new BigNumber(1); const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrdersUpToAsync( cancelOrdersUpToThisSalt, - compliantSignedOrder.makerAddress, + validSignedOrder.makerAddress, ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - _.each(compliantSignedOrders, async (signedOrder, salt: number) => { + _.each(validSignedOrders, async (signedOrder, salt: number) => { const orderInfoAfterCancelling = await erc721MakerBalanceThresholdWrapper.getOrderInfoAsync( signedOrder, ); @@ -1654,30 +1625,30 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('Should successfully batch cancel order if maker does not meet balance threshold', async () => { // Create orders to cancel - const nonCompliantSignedOrders = [ - await nonCompliantOrderFactory.newSignedOrderAsync({ salt: new BigNumber(0) }), - await nonCompliantOrderFactory.newSignedOrderAsync({ salt: new BigNumber(1) }), - await nonCompliantOrderFactory.newSignedOrderAsync({ salt: new BigNumber(2) }), + const invalidSignedOrders = [ + await invalidOrderFactory.newSignedOrderAsync({ salt: new BigNumber(0) }), + await invalidOrderFactory.newSignedOrderAsync({ salt: new BigNumber(1) }), + await invalidOrderFactory.newSignedOrderAsync({ salt: new BigNumber(2) }), ]; // Verify orders are not cancelled - _.each(nonCompliantSignedOrders, async signedOrder => { - const orderInfoBeforeCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + _.each(invalidSignedOrders, async signedOrder => { + const orderInfoBeforeCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync( signedOrder, ); return expect(orderInfoBeforeCancelling.orderStatus).to.be.equal(OrderStatus.FILLABLE); }); // Cancel const cancelOrdersUpToThisSalt = new BigNumber(1); - const txReceipt = await erc721NonCompliantBalanceThresholdWrapper.cancelOrdersUpToAsync( + const txReceipt = await erc721NonValidBalanceThresholdWrapper.cancelOrdersUpToAsync( cancelOrdersUpToThisSalt, - nonCompliantAddress, + invalidAddress, ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check that order was cancelled - _.each(nonCompliantSignedOrders, async (signedOrder, salt: number) => { - const orderInfoAfterCancelling = await erc721NonCompliantBalanceThresholdWrapper.getOrderInfoAsync( + _.each(invalidSignedOrders, async (signedOrder, salt: number) => { + const orderInfoAfterCancelling = await erc721NonValidBalanceThresholdWrapper.getOrderInfoAsync( signedOrder, ); const saltAsBigNumber = new BigNumber(salt); -- cgit v1.2.3 From 22fd23643cb26ba1b79e9b13e5ef41c97ab7fe6a Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 11 Dec 2018 16:37:07 -0800 Subject: Run all tests for extensions --- contracts/extensions/test/extensions/balance_threshold_filter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts index ced9d6e25..6350c019f 100644 --- a/contracts/extensions/test/extensions/balance_threshold_filter.ts +++ b/contracts/extensions/test/extensions/balance_threshold_filter.ts @@ -46,7 +46,7 @@ interface ValidatedAddressesLog { args: { addresses: string[] }; } -describe.only(ContractName.BalanceThresholdFilter, () => { +describe(ContractName.BalanceThresholdFilter, () => { const takerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(500), DECIMALS_DEFAULT); const makerAssetAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), DECIMALS_DEFAULT); const takerAssetFillAmount = Web3Wrapper.toBaseUnitAmount(new BigNumber(250), DECIMALS_DEFAULT); -- cgit v1.2.3 From f91781a0605f46ee1a40bf979d22ff510f48d464 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 13 Dec 2018 13:52:20 -0800 Subject: Less Assembly. More Solidity. Less Efficiency. More Readability. --- .../BalanceThresholdFilter.sol | 10 +- .../MixinBalanceThresholdFilterCore.sol | 404 ++++++++------------- .../mixins/MBalanceThresholdFilterCore.sol | 7 +- 3 files changed, 155 insertions(+), 266 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol b/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol index a68f6805d..ea248793f 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol @@ -24,21 +24,23 @@ import "./interfaces/IThresholdAsset.sol"; import "./MixinBalanceThresholdFilterCore.sol"; -contract BalanceThresholdFilter is MixinBalanceThresholdFilterCore { +contract BalanceThresholdFilter is + MixinBalanceThresholdFilterCore +{ /// @dev Constructs BalanceThresholdFilter. /// @param exchange Address of 0x exchange. /// @param thresholdAsset The asset that must be held by makers/takers. - /// @param thresholdBalance The minimum balance of `thresholdAsset` that must be held by makers/takers. + /// @param balanceThreshold The minimum balance of `thresholdAsset` that must be held by makers/takers. constructor( address exchange, address thresholdAsset, - uint256 thresholdBalance + uint256 balanceThreshold ) public { EXCHANGE = IExchange(exchange); THRESHOLD_ASSET = IThresholdAsset(thresholdAsset); - THRESHOLD_BALANCE = thresholdBalance; + BALANCE_THRESHOLD = balanceThreshold; } } diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index 51dbae8f3..e78f9ced8 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -6,7 +6,7 @@ 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 + http://www.apache.org/licenses/LICENSE2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -17,31 +17,36 @@ */ pragma solidity 0.4.24; -pragma experimental ABIEncoderV2; import "./mixins/MBalanceThresholdFilterCore.sol"; +import "@0x/contracts-utils/contracts/utils/ExchangeSelectors/ExchangeSelectors.sol"; +import "@0x/contracts-libs/contracts/libs/LibOrder.sol"; -contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { +contract MixinBalanceThresholdFilterCore is + MBalanceThresholdFilterCore, + LibOrder, + ExchangeSelectors +{ /// @dev Executes an Exchange transaction iff the maker and taker meet /// the hold at least `BALANCE_THRESHOLD` of the asset `THRESHOLD_ASSET` OR /// the exchange function is a cancellation. /// Supported Exchange functions: - /// - batchFillOrders - /// - batchFillOrdersNoThrow - /// - batchFillOrKillOrders - /// - fillOrder - /// - fillOrderNoThrow - /// - fillOrKillOrder - /// - marketBuyOrders - /// - marketBuyOrdersNoThrow - /// - marketSellOrders - /// - marketSellOrdersNoThrow - /// - matchOrders - /// - cancelOrder - /// - batchCancelOrders - /// - cancelOrdersUpTo + /// batchFillOrders + /// batchFillOrdersNoThrow + /// batchFillOrKillOrders + /// fillOrder + /// fillOrderNoThrow + /// fillOrKillOrder + /// marketBuyOrders + /// marketBuyOrdersNoThrow + /// marketSellOrders + /// marketSellOrdersNoThrow + /// matchOrders + /// cancelOrder + /// batchCancelOrders + /// cancelOrdersUpTo /// Trying to call any other exchange function will throw. /// @param salt Arbitrary number to ensure uniqueness of transaction hash. /// @param signerAddress Address of transaction signer. @@ -56,7 +61,7 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { external { // Validate addresses. - validateBalanceThresholdsOrRevert(); + validateBalanceThresholdsOrRevert(signerAddress); // All addresses are valid. Execute fillOrder. EXCHANGE.executeTransaction( @@ -67,6 +72,83 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { ); } + /// @dev Emulates the `calldataload` opcode on the embedded Exchange calldata, + /// which is accessed through `signedExchangeTransaction`. + /// @param offset Offset into the Exchange calldata. + /// @return value Corresponding 32 byte value stored at `offset`. + function exchangeCalldataload(uint256 offset) + internal + returns (bytes32 value) + { + assembly { + // Pointer to exchange transaction + // 0x04 for calldata selector + // 0x40 to access `signedExchangeTransaction`, which is the third parameter + let exchangeTxPtr := calldataload(0x44) + + // Offset into Exchange calldata + // We compute this by adding 0x24 to the `exchangeTxPtr` computed above. + // 0x04 for calldata selector + // 0x20 for length field of `signedExchangeTransaction` + let exchangeCalldataOffset := add(exchangeTxPtr, add(0x24, offset)) + value := calldataload(exchangeCalldataOffset) + } + } + + /// @dev Convenience function that skips the 4 byte selector when loading + /// from the embedded Exchange calldata. + /// @param offset Offset into the Exchange calldata (minus the 4 byte selector) + /// @return value Corresponding 32 byte value stored at `offset` + 4. + function loadExchangeData(uint256 offset) + internal + returns (bytes32 value) + { + value = exchangeCalldataload(offset + 4); + } + + /// @dev A running list is maintained of addresses to validate. + /// This function records an address in this array. + /// @param addressToValidate Address to record for validation. + function recordAddressToValidate(address addressToValidate, address[] memory addressList) + internal + { + uint256 newAddressListLength = addressList.length + 1; + assembly { + // Store new array length + mstore(addressList, newAddressListLength) + mstore(0x40, add(addressList, add(0x20, mul(0x20, newAddressListLength)))) + } + addressList[newAddressListLength - 1] = addressToValidate; + } + + /// @dev Extracts the maker address from an order stored in the Exchange calldata + /// (which is embedded in `signedExchangeTransaction`), and records it in + /// the running list of addresses to validate. + /// @param orderParamIndex Index of the order in the Exchange function's signature + function loadMakerAddressFromOrder(uint8 orderParamIndex) internal returns (address makerAddress) { + uint256 orderPtr = uint256(loadExchangeData(orderParamIndex * 0x20)); + makerAddress = address(loadExchangeData(orderPtr)); + } + + /// @dev Extracts the maker addresses from an array of orders stored in the Exchange calldata + /// (which is embedded in `signedExchangeTransaction`), and records them in + /// the running list of addresses to validate. + /// @param orderArrayParamIndex Index of the order array in the Exchange function's signature + function loadMakerAddressesFromOrderArray(uint8 orderArrayParamIndex) + internal + returns (address[] makerAddresses) + { + uint256 orderArrayPtr = uint256(loadExchangeData(orderArrayParamIndex * 0x20)); + uint256 orderArrayLength = uint256(loadExchangeData(orderArrayPtr)); + uint256 orderArrayElementPtr = orderArrayPtr + 0x20; + uint256 orderArrayElementEndPtr = orderArrayElementPtr + (orderArrayLength * 0x20); + for(uint orderPtrOffset = orderArrayElementPtr; orderPtrOffset < orderArrayElementEndPtr; orderPtrOffset += 0x20) { + uint256 orderPtr = uint256(loadExchangeData(orderPtrOffset)); + address makerAddress = address(loadExchangeData(orderPtr + orderArrayElementPtr)); + recordAddressToValidate(makerAddress, makerAddresses); + } + } + /// @dev Validates addresses meet the balance threshold specified by `BALANCE_THRESHOLD` /// for the asset `THRESHOLD_ASSET`. If one address does not meet the thresold /// then this function will revert. Which addresses are validated depends on @@ -74,250 +156,56 @@ contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore { /// No parameters are taken as this function reads arguments directly from calldata, to save gas. /// If all addresses are valid then this function emits a ValidatedAddresses event, listing all /// of the addresses whose balance thresholds it checked. - function validateBalanceThresholdsOrRevert() + function validateBalanceThresholdsOrRevert(address signerAddress) internal { - // Addresses that are validated below. - address[] memory validatedAddresses; - - ///// Do not add variables after this point. ///// - ///// The assembly block may overwrite their values. ///// - - // Validate addresses - assembly { - /// @dev Emulates the `calldataload` opcode on the embedded Exchange calldata, - /// which is accessed through `signedExchangeTransaction`. - /// @param offset - Offset into the Exchange calldata. - /// @return value - Corresponding 32 byte value stored at `offset`. - function exchangeCalldataload(offset) -> value { - // Pointer to exchange transaction - // 0x04 for calldata selector - // 0x40 to access `signedExchangeTransaction`, which is the third parameter - let exchangeTxPtr := calldataload(0x44) - - // Offset into Exchange calldata - // We compute this by adding 0x24 to the `exchangeTxPtr` computed above. - // 0x04 for calldata selector - // 0x20 for length field of `signedExchangeTransaction` - let exchangeCalldataOffset := add(exchangeTxPtr, add(0x24, offset)) - value := calldataload(exchangeCalldataOffset) - } - - /// @dev Convenience function that skips the 4 byte selector when loading - /// from the embedded Exchange calldata. - /// @param offset - Offset into the Exchange calldata (minus the 4 byte selector) - /// @return value - Corresponding 32 byte value stored at `offset` + 4. - function loadExchangeData(offset) -> value { - value := exchangeCalldataload(add(offset, 0x4)) - } - - /// @dev A running list is maintained of addresses to validate. - /// This function records an address in this array. - /// @param addressToValidate - Address to record for validation. - function recordAddressToValidate(addressToValidate) { - // Compute `addressesToValidate` memory offset - let addressesToValidate_ := mload(0x40) - let nAddressesToValidate_ := mload(addressesToValidate_) - - // Increment length - nAddressesToValidate_ := add(mload(addressesToValidate_), 0x01) - mstore(addressesToValidate_, nAddressesToValidate_) - - // Append address to validate - let offset := mul(nAddressesToValidate_, 0x20) - mstore(add(addressesToValidate_, offset), addressToValidate) - } - - /// @dev Extracts the maker address from an order stored in the Exchange calldata - /// (which is embedded in `signedExchangeTransaction`), and records it in - /// the running list of addresses to validate. - /// @param orderParamIndex - Index of the order in the Exchange function's signature - function recordMakerAddressFromOrder(orderParamIndex) { - let orderPtr := loadExchangeData(mul(orderParamIndex, 0x20)) - let makerAddress := loadExchangeData(orderPtr) - recordAddressToValidate(makerAddress) - } - - /// @dev Extracts the maker addresses from an array of orders stored in the Exchange calldata - /// (which is embedded in `signedExchangeTransaction`), and records them in - /// the running list of addresses to validate. - /// @param orderArrayParamIndex - Index of the order array in the Exchange function's signature - function recordMakerAddressesFromOrderArray(orderArrayParamIndex) { - let orderArrayPtr := loadExchangeData(mul(orderArrayParamIndex, 0x20)) - let orderArrayLength := loadExchangeData(orderArrayPtr) - let orderArrayElementPtr := add(orderArrayPtr, 0x20) - let orderArrayElementEndPtr := add(orderArrayElementPtr, mul(orderArrayLength, 0x20)) - for {let orderPtrOffset := orderArrayElementPtr} lt(orderPtrOffset, orderArrayElementEndPtr) {orderPtrOffset := add(orderPtrOffset, 0x20)} { - let orderPtr := loadExchangeData(orderPtrOffset) - let makerAddress := loadExchangeData(add(orderPtr, orderArrayElementPtr)) - recordAddressToValidate(makerAddress) - } - } - - /// @dev Records address of signer in the running list of addresses to validate. - /// @note: We cannot access `signerAddress` directly from within the asm function, - /// so it is loaded from the calldata. - function recordSignerAddress() { - // Load the signer address from calldata - // 0x04 for selector - // 0x20 to access `signerAddress`, which is the second parameter. - let signerAddress_ := calldataload(0x24) - recordAddressToValidate(signerAddress_) - } - - /// @dev Records addresses to be validated when Exchange transaction is a batch fill variant. - /// This is one of: batchFillOrders, batchFillOrKillOrders, batchFillNoThrow - /// Reference signature: (Order[],uint256[],bytes[]) - function recordAddressesForBatchFillVariant() { - // Record maker addresses from order array (parameter index 0) - // The signer is the taker for these orders and must also be validated. - recordMakerAddressesFromOrderArray(0) - recordSignerAddress() - } - - /// @dev Records addresses to be validated when Exchange transaction is a fill order variant. - /// This is one of: fillOrder, fillOrKillOrder, fillOrderNoThrow - /// Reference signature: (Order,uint256,bytes) - function recordAddressesForFillOrderVariant() { - // Record maker address from the order (param index 0) - // The signer is the taker for this order and must also be validated. - recordMakerAddressFromOrder(0) - recordSignerAddress() - } - - /// @dev Records addresses to be validated when Exchange transaction is a market fill variant. - /// This is one of: marketBuyOrders, marketBuyOrdersNoThrow, marketSellOrders, marketSellOrdersNoThrow - /// Reference signature: (Order[],uint256,bytes[]) - function recordAddressesForMarketFillVariant() { - // Record maker addresses from order array (parameter index 0) - // The signer is the taker for these orders and must also be validated. - recordMakerAddressesFromOrderArray(0) - recordSignerAddress() - } - - /// @dev Records addresses to be validated when Exchange transaction is matchOrders. - /// Reference signature: matchOrders(Order,Order) - function recordAddressesForMatchOrders() { - // Record maker address from both orders (param indices 0 & 1). - // The signer is the taker and must also be validated. - recordMakerAddressFromOrder(0) - recordMakerAddressFromOrder(1) - recordSignerAddress() - } - - ///// Record Addresses to Validate ///// - - // Addresses needing validation depends on which Exchange function is being called. - // Step 1/2 Read the exchange function selector. - let exchangeFunctionSelector := and( - exchangeCalldataload(0x0), - 0xffffffff00000000000000000000000000000000000000000000000000000000 - ) - - // Step 2/2 Extract addresses to validate based on this selector. - // See ../../utils/ExchangeSelectors/ExchangeSelectors.sol for selectors - // solhint-disable no-empty-blocks - switch exchangeFunctionSelector - case 0x297bb70b00000000000000000000000000000000000000000000000000000000 { recordAddressesForBatchFillVariant() } // batchFillOrders - case 0x50dde19000000000000000000000000000000000000000000000000000000000 { recordAddressesForBatchFillVariant() } // batchFillOrdersNoThrow - case 0x4d0ae54600000000000000000000000000000000000000000000000000000000 { recordAddressesForBatchFillVariant() } // batchFillOrKillOrders - case 0xb4be83d500000000000000000000000000000000000000000000000000000000 { recordAddressesForFillOrderVariant() } // fillOrder - case 0x3e228bae00000000000000000000000000000000000000000000000000000000 { recordAddressesForFillOrderVariant() } // fillOrderNoThrow - case 0x64a3bc1500000000000000000000000000000000000000000000000000000000 { recordAddressesForFillOrderVariant() } // fillOrKillOrder - case 0xe5fa431b00000000000000000000000000000000000000000000000000000000 { recordAddressesForMarketFillVariant() } // marketBuyOrders - case 0xa3e2038000000000000000000000000000000000000000000000000000000000 { recordAddressesForMarketFillVariant() } // marketBuyOrdersNoThrow - case 0x7e1d980800000000000000000000000000000000000000000000000000000000 { recordAddressesForMarketFillVariant() } // marketSellOrders - case 0xdd1c7d1800000000000000000000000000000000000000000000000000000000 { recordAddressesForMarketFillVariant() } // marketSellOrdersNoThrow - case 0x3c28d86100000000000000000000000000000000000000000000000000000000 { recordAddressesForMatchOrders() } // matchOrders - case 0xd46b02c300000000000000000000000000000000000000000000000000000000 {} // cancelOrder - case 0x4ac1478200000000000000000000000000000000000000000000000000000000 {} // batchCancelOrders - case 0x4f9559b100000000000000000000000000000000000000000000000000000000 {} // cancelOrdersUpTo - default { - // Revert with `Error("INVALID_OR_BLOCKED_EXCHANGE_SELECTOR")` - mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) - mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000) - mstore(0x40, 0x00000024494e56414c49445f4f525f424c4f434b45445f45584348414e47455f) - mstore(0x60, 0x53454c4543544f52000000000000000000000000000000000000000000000000) - mstore(0x80, 0x00000000) - // Revert length calculation: - // 4 -- error selector - // 32 -- offset to string - // 32 -- string length field - // 64 -- strlen(INVALID_OR_BLOCKED_EXCHANGE_SELECTOR) rounded up to nearest 32-byte word. - revert(0, 132) - } - // solhint-enable no-empty-blocks - - ///// Validate Recorded Addresses ///// - - // Load from memory the addresses to validate - let addressesToValidate := mload(0x40) - let addressesToValidateLength := mload(addressesToValidate) - let addressesToValidateElementPtr := add(addressesToValidate, 0x20) - let addressesToValidateElementEndPtr := add(addressesToValidateElementPtr, mul(addressesToValidateLength, 0x20)) - - // Set free memory pointer to after `addressesToValidate` array. - // This is to avoid corruption when making calls in the loop below. - let freeMemPtr := addressesToValidateElementEndPtr - mstore(0x40, freeMemPtr) - - // Validate addresses - let thresholdAssetAddress := sload(THRESHOLD_ASSET_slot) - let thresholdBalance := sload(THRESHOLD_BALANCE_slot) - // solhint-disable max-line-length - for {let addressToValidate := addressesToValidateElementPtr} lt(addressToValidate, addressesToValidateElementEndPtr) {addressToValidate := add(addressToValidate, 0x20)} { - // solhint-enable max-line-length - // Construct calldata for `THRESHOLD_ASSET.balanceOf` - mstore(freeMemPtr, 0x70a0823100000000000000000000000000000000000000000000000000000000) - mstore(add(freeMemPtr, 0x04), mload(addressToValidate)) - - // call `THRESHOLD_ASSET.balanceOf` - let success := call( - gas, // forward all gas - thresholdAssetAddress, // call address of asset proxy - 0, // don't send any ETH - freeMemPtr, // pointer to start of input - 0x24, // length of input (one padded address) - freeMemPtr, // write output to next free memory offset - 0x20 // reserve space for return balance (0x20 bytes) - ) - if eq(success, 0) { - // @TODO Revert with `Error("BALANCE_QUERY_FAILED")` - mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) - mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000) - mstore(0x40, 0x0000001442414c414e43455f51554552595f4641494c45440000000000000000) - mstore(0x60, 0x00000000) - // Revert length calculation: - // 4 -- error selector - // 32 -- offset to string - // 32 -- string length field - // 32 -- strlen(BALANCE_QUERY_FAILED) rounded up to nearest 32-byte word. - revert(0, 100) - } + // Extract addresses to validate from Exchange calldata + address[] memory addressesToValidate = new address[](0); + bytes4 exchangeFunctionSelector = bytes4(exchangeCalldataload(0)); + if( + exchangeFunctionSelector == batchFillOrdersSelector || + exchangeFunctionSelector == batchFillOrdersNoThrowSelector || + exchangeFunctionSelector == batchFillOrKillOrdersSelector || + exchangeFunctionSelector == marketBuyOrdersSelector || + exchangeFunctionSelector == marketBuyOrdersNoThrowSelector || + exchangeFunctionSelector == marketSellOrdersSelector || + exchangeFunctionSelector == marketSellOrdersNoThrowSelector + ) { + addressesToValidate = loadMakerAddressesFromOrderArray(0); + recordAddressToValidate(signerAddress, addressesToValidate); + } else if( + exchangeFunctionSelector == fillOrderSelector || + exchangeFunctionSelector == fillOrderNoThrowSelector || + exchangeFunctionSelector == fillOrKillOrderSelector + ) { + address makerAddress = loadMakerAddressFromOrder(0); + recordAddressToValidate(makerAddress, addressesToValidate); + recordAddressToValidate(signerAddress, addressesToValidate); + } else if(exchangeFunctionSelector == matchOrdersSelector) { + address leftOrderAddress = loadMakerAddressFromOrder(0); + recordAddressToValidate(leftOrderAddress, addressesToValidate); + address rightOrderAddress = loadMakerAddressFromOrder(1); + recordAddressToValidate(rightOrderAddress, addressesToValidate); + recordAddressToValidate(signerAddress, addressesToValidate); + } else if( + exchangeFunctionSelector == cancelOrderSelector || + exchangeFunctionSelector == batchCancelOrdersSelector || + exchangeFunctionSelector == cancelOrdersUpToSelector + ) { + // Do nothing + } else { + revert("INVALID_OR_BLOCKED_EXCHANGE_SELECTOR"); + } - // Revert if balance not held - let addressBalance := mload(freeMemPtr) - if lt(addressBalance, thresholdBalance) { - // Revert with `Error("AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD")` - mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) - mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000) - mstore(0x40, 0x0000003441545f4c454153545f4f4e455f414444524553535f444f45535f4e4f) - mstore(0x60, 0x545f4d4545545f42414c414e43455f5448524553484f4c440000000000000000) - mstore(0x80, 0x00000000) - // Revert length calculation: - // 4 -- error selector - // 32 -- offset to string - // 32 -- string length field - // 64 -- strlen(AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD) rounded up to nearest 32-byte word. - revert(0, 132) - } + // Validate account balances + uint256 balanceThreshold = BALANCE_THRESHOLD; + IThresholdAsset thresholdAsset = THRESHOLD_ASSET; + for(uint i = 0; i < addressesToValidate.length; ++i) { + uint256 addressBalance = thresholdAsset.balanceOf(addressesToValidate[i]); + if (addressBalance < balanceThreshold) { + revert("AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD"); } - - // Record validated addresses - validatedAddresses := addressesToValidate } - - ///// If we hit this point then all addresses are valid ///// - emit ValidatedAddresses(validatedAddresses); + emit ValidatedAddresses(addressesToValidate); } } diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol index af7a9453b..6aaa729fb 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol @@ -17,7 +17,6 @@ */ pragma solidity 0.4.24; -pragma experimental ABIEncoderV2; import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol"; import "../interfaces/IThresholdAsset.sol"; @@ -33,10 +32,10 @@ contract MBalanceThresholdFilterCore { IThresholdAsset internal THRESHOLD_ASSET; // The minimum balance of `THRESHOLD_ASSET` that must be held by makers/takers - uint256 internal THRESHOLD_BALANCE; + uint256 internal BALANCE_THRESHOLD; // solhint-enable var-name-mixedcase - // Addresses that hold at least `THRESHOLD_BALANCE` of `THRESHOLD_ASSET` + // Addresses that hold at least `BALANCE_THRESHOLD` of `THRESHOLD_ASSET` event ValidatedAddresses ( address[] addresses ); @@ -79,5 +78,5 @@ contract MBalanceThresholdFilterCore { /// No parameters are taken as this function reads arguments directly from calldata, to save gas. /// If all addresses are valid then this function emits a ValidatedAddresses event, listing all /// of the addresses whose balance thresholds it checked. - function validateBalanceThresholdsOrRevert() internal; + function validateBalanceThresholdsOrRevert(address signerAddress) internal; } -- cgit v1.2.3 From f3a2e3b6f3adb75d1920779df9dabb7cf476a996 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 13 Dec 2018 14:20:11 -0800 Subject: Moved exchange calldata functions to separate mixin --- .../MixinBalanceThresholdFilterCore.sol | 93 +++------------------- 1 file changed, 9 insertions(+), 84 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index e78f9ced8..8d15fe6c8 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -18,15 +18,17 @@ pragma solidity 0.4.24; -import "./mixins/MBalanceThresholdFilterCore.sol"; -import "@0x/contracts-utils/contracts/utils/ExchangeSelectors/ExchangeSelectors.sol"; +import "@0x/contracts-libs/contracts/libs/LibExchangeSelectors.sol"; import "@0x/contracts-libs/contracts/libs/LibOrder.sol"; +import "./mixins/MBalanceThresholdFilterCore.sol"; +import "./MixinExchangeCalldata.sol"; contract MixinBalanceThresholdFilterCore is MBalanceThresholdFilterCore, + MixinExchangeCalldata, LibOrder, - ExchangeSelectors + LibExchangeSelectors { /// @dev Executes an Exchange transaction iff the maker and taker meet @@ -72,82 +74,7 @@ contract MixinBalanceThresholdFilterCore is ); } - /// @dev Emulates the `calldataload` opcode on the embedded Exchange calldata, - /// which is accessed through `signedExchangeTransaction`. - /// @param offset Offset into the Exchange calldata. - /// @return value Corresponding 32 byte value stored at `offset`. - function exchangeCalldataload(uint256 offset) - internal - returns (bytes32 value) - { - assembly { - // Pointer to exchange transaction - // 0x04 for calldata selector - // 0x40 to access `signedExchangeTransaction`, which is the third parameter - let exchangeTxPtr := calldataload(0x44) - - // Offset into Exchange calldata - // We compute this by adding 0x24 to the `exchangeTxPtr` computed above. - // 0x04 for calldata selector - // 0x20 for length field of `signedExchangeTransaction` - let exchangeCalldataOffset := add(exchangeTxPtr, add(0x24, offset)) - value := calldataload(exchangeCalldataOffset) - } - } - - /// @dev Convenience function that skips the 4 byte selector when loading - /// from the embedded Exchange calldata. - /// @param offset Offset into the Exchange calldata (minus the 4 byte selector) - /// @return value Corresponding 32 byte value stored at `offset` + 4. - function loadExchangeData(uint256 offset) - internal - returns (bytes32 value) - { - value = exchangeCalldataload(offset + 4); - } - - /// @dev A running list is maintained of addresses to validate. - /// This function records an address in this array. - /// @param addressToValidate Address to record for validation. - function recordAddressToValidate(address addressToValidate, address[] memory addressList) - internal - { - uint256 newAddressListLength = addressList.length + 1; - assembly { - // Store new array length - mstore(addressList, newAddressListLength) - mstore(0x40, add(addressList, add(0x20, mul(0x20, newAddressListLength)))) - } - addressList[newAddressListLength - 1] = addressToValidate; - } - - /// @dev Extracts the maker address from an order stored in the Exchange calldata - /// (which is embedded in `signedExchangeTransaction`), and records it in - /// the running list of addresses to validate. - /// @param orderParamIndex Index of the order in the Exchange function's signature - function loadMakerAddressFromOrder(uint8 orderParamIndex) internal returns (address makerAddress) { - uint256 orderPtr = uint256(loadExchangeData(orderParamIndex * 0x20)); - makerAddress = address(loadExchangeData(orderPtr)); - } - - /// @dev Extracts the maker addresses from an array of orders stored in the Exchange calldata - /// (which is embedded in `signedExchangeTransaction`), and records them in - /// the running list of addresses to validate. - /// @param orderArrayParamIndex Index of the order array in the Exchange function's signature - function loadMakerAddressesFromOrderArray(uint8 orderArrayParamIndex) - internal - returns (address[] makerAddresses) - { - uint256 orderArrayPtr = uint256(loadExchangeData(orderArrayParamIndex * 0x20)); - uint256 orderArrayLength = uint256(loadExchangeData(orderArrayPtr)); - uint256 orderArrayElementPtr = orderArrayPtr + 0x20; - uint256 orderArrayElementEndPtr = orderArrayElementPtr + (orderArrayLength * 0x20); - for(uint orderPtrOffset = orderArrayElementPtr; orderPtrOffset < orderArrayElementEndPtr; orderPtrOffset += 0x20) { - uint256 orderPtr = uint256(loadExchangeData(orderPtrOffset)); - address makerAddress = address(loadExchangeData(orderPtr + orderArrayElementPtr)); - recordAddressToValidate(makerAddress, makerAddresses); - } - } + /// @dev Validates addresses meet the balance threshold specified by `BALANCE_THRESHOLD` /// for the asset `THRESHOLD_ASSET`. If one address does not meet the thresold @@ -188,12 +115,10 @@ contract MixinBalanceThresholdFilterCore is recordAddressToValidate(rightOrderAddress, addressesToValidate); recordAddressToValidate(signerAddress, addressesToValidate); } else if( - exchangeFunctionSelector == cancelOrderSelector || - exchangeFunctionSelector == batchCancelOrdersSelector || - exchangeFunctionSelector == cancelOrdersUpToSelector + exchangeFunctionSelector != cancelOrderSelector && + exchangeFunctionSelector != batchCancelOrdersSelector && + exchangeFunctionSelector != cancelOrdersUpToSelector ) { - // Do nothing - } else { revert("INVALID_OR_BLOCKED_EXCHANGE_SELECTOR"); } -- cgit v1.2.3 From dea6f35b0471913551d58a08f547974701fc0057 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 13 Dec 2018 14:26:11 -0800 Subject: Refactoring balance threshold filter --- .../BalanceThresholdFilter.sol | 1 - .../MixinBalanceThresholdFilterCore.sol | 63 ++++++------- .../MixinExchangeCalldata.sol | 102 +++++++++++++++++++++ .../interfaces/IBalanceThresholdFilterCore.sol | 56 +++++++++++ .../mixins/MBalanceThresholdFilterCore.sol | 50 +++------- .../mixins/MExchangeCalldata.sol | 57 ++++++++++++ 6 files changed, 255 insertions(+), 74 deletions(-) create mode 100644 contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol create mode 100644 contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IBalanceThresholdFilterCore.sol create mode 100644 contracts/extensions/contracts/BalanceThresholdFilter/mixins/MExchangeCalldata.sol (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol b/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol index ea248793f..16cacd461 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/BalanceThresholdFilter.sol @@ -17,7 +17,6 @@ */ pragma solidity 0.4.24; -pragma experimental ABIEncoderV2; import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol"; import "./interfaces/IThresholdAsset.sol"; diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index 8d15fe6c8..a8947751a 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -62,8 +62,19 @@ contract MixinBalanceThresholdFilterCore is ) external { - // Validate addresses. - validateBalanceThresholdsOrRevert(signerAddress); + // Get accounts whose balances must be validated + address[] memory addressesToValidate = getAddressesToValidate(signerAddress); + + // Validate account balances + uint256 balanceThreshold = BALANCE_THRESHOLD; + IThresholdAsset thresholdAsset = THRESHOLD_ASSET; + for(uint256 i = 0; i < addressesToValidate.length; ++i) { + uint256 addressBalance = thresholdAsset.balanceOf(addressesToValidate[i]); + if (addressBalance < balanceThreshold) { + revert("AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD"); + } + } + emit ValidatedAddresses(addressesToValidate); // All addresses are valid. Execute fillOrder. EXCHANGE.executeTransaction( @@ -74,20 +85,15 @@ contract MixinBalanceThresholdFilterCore is ); } - - - /// @dev Validates addresses meet the balance threshold specified by `BALANCE_THRESHOLD` - /// for the asset `THRESHOLD_ASSET`. If one address does not meet the thresold - /// then this function will revert. Which addresses are validated depends on - /// which Exchange function is to be called (defined by `signedExchangeTransaction` above). - /// No parameters are taken as this function reads arguments directly from calldata, to save gas. - /// If all addresses are valid then this function emits a ValidatedAddresses event, listing all - /// of the addresses whose balance thresholds it checked. - function validateBalanceThresholdsOrRevert(address signerAddress) - internal + /// @dev Constructs an array of addresses to be validated. + /// Addresses depend on which Exchange function is to be called + /// (defined by `signedExchangeTransaction` above). + /// @param signerAddress Address of transaction signer. + /// @return addressesToValidate Array of addresses to validate. + function getAddressesToValidate(address signerAddress) + internal pure + returns (address[] memory addressesToValidate) { - // Extract addresses to validate from Exchange calldata - address[] memory addressesToValidate = new address[](0); bytes4 exchangeFunctionSelector = bytes4(exchangeCalldataload(0)); if( exchangeFunctionSelector == batchFillOrdersSelector || @@ -99,21 +105,21 @@ contract MixinBalanceThresholdFilterCore is exchangeFunctionSelector == marketSellOrdersNoThrowSelector ) { addressesToValidate = loadMakerAddressesFromOrderArray(0); - recordAddressToValidate(signerAddress, addressesToValidate); + addressesToValidate = addressesToValidate.append(signerAddress); } else if( exchangeFunctionSelector == fillOrderSelector || exchangeFunctionSelector == fillOrderNoThrowSelector || exchangeFunctionSelector == fillOrKillOrderSelector ) { address makerAddress = loadMakerAddressFromOrder(0); - recordAddressToValidate(makerAddress, addressesToValidate); - recordAddressToValidate(signerAddress, addressesToValidate); + addressesToValidate = addressesToValidate.append(makerAddress); + addressesToValidate = addressesToValidate.append(signerAddress); } else if(exchangeFunctionSelector == matchOrdersSelector) { - address leftOrderAddress = loadMakerAddressFromOrder(0); - recordAddressToValidate(leftOrderAddress, addressesToValidate); - address rightOrderAddress = loadMakerAddressFromOrder(1); - recordAddressToValidate(rightOrderAddress, addressesToValidate); - recordAddressToValidate(signerAddress, addressesToValidate); + address leftMakerAddress = loadMakerAddressFromOrder(0); + addressesToValidate = addressesToValidate.append(leftMakerAddress); + address rightMakerAddress = loadMakerAddressFromOrder(1); + addressesToValidate = addressesToValidate.append(rightMakerAddress); + addressesToValidate = addressesToValidate.append(signerAddress); } else if( exchangeFunctionSelector != cancelOrderSelector && exchangeFunctionSelector != batchCancelOrdersSelector && @@ -121,16 +127,5 @@ contract MixinBalanceThresholdFilterCore is ) { revert("INVALID_OR_BLOCKED_EXCHANGE_SELECTOR"); } - - // Validate account balances - uint256 balanceThreshold = BALANCE_THRESHOLD; - IThresholdAsset thresholdAsset = THRESHOLD_ASSET; - for(uint i = 0; i < addressesToValidate.length; ++i) { - uint256 addressBalance = thresholdAsset.balanceOf(addressesToValidate[i]); - if (addressBalance < balanceThreshold) { - revert("AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD"); - } - } - emit ValidatedAddresses(addressesToValidate); } } diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol new file mode 100644 index 000000000..12f601dea --- /dev/null +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol @@ -0,0 +1,102 @@ + + /* + + Copyright 2018 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/LICENSE2.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.4.24; + +import "./mixins/MExchangeCalldata.sol"; +import "@0x/contracts-libs/contracts/libs/LibAddressArray.sol"; + + +contract MixinExchangeCalldata is + MExchangeCalldata +{ + + using LibAddressArray for address[]; + + /// @dev Emulates the `calldataload` opcode on the embedded Exchange calldata, + /// which is accessed through `signedExchangeTransaction`. + /// @param offset Offset into the Exchange calldata. + /// @return value Corresponding 32 byte value stored at `offset`. + function exchangeCalldataload(uint256 offset) + internal pure + returns (bytes32 value) + { + assembly { + // Pointer to exchange transaction + // 0x04 for calldata selector + // 0x40 to access `signedExchangeTransaction`, which is the third parameter + let exchangeTxPtr := calldataload(0x44) + + // Offset into Exchange calldata + // We compute this by adding 0x24 to the `exchangeTxPtr` computed above. + // 0x04 for calldata selector + // 0x20 for length field of `signedExchangeTransaction` + let exchangeCalldataOffset := add(exchangeTxPtr, add(0x24, offset)) + value := calldataload(exchangeCalldataOffset) + } + } + + /// @dev Convenience function that skips the 4 byte selector when loading + /// from the embedded Exchange calldata. + /// @param offset Offset into the Exchange calldata (minus the 4 byte selector) + /// @return value Corresponding 32 byte value stored at `offset` + 4. + function loadExchangeData(uint256 offset) + internal pure + returns (bytes32 value) + { + value = exchangeCalldataload(offset + 4); + } + + /// @dev Extracts the maker address from an order stored in the Exchange calldata + /// (which is embedded in `signedExchangeTransaction`). + /// @param orderParamIndex Index of the order in the Exchange function's signature. + /// @return makerAddress The extracted maker address. + function loadMakerAddressFromOrder(uint256 orderParamIndex) + internal pure + returns (address makerAddress) + { + uint256 orderOffsetInBytes = orderParamIndex * 32; + uint256 orderPtr = uint256(loadExchangeData(orderOffsetInBytes)); + makerAddress = address(loadExchangeData(orderPtr)); + return makerAddress; + } + + /// @dev Extracts the maker addresses from an array of orders stored in the Exchange calldata + /// (which is embedded in `signedExchangeTransaction`), and records them in + /// the running list of addresses to validate. + /// @param orderArrayParamIndex Index of the order array in the Exchange function's signature + /// @return makerAddresses The extracted maker addresses. + function loadMakerAddressesFromOrderArray(uint256 orderArrayParamIndex) + internal pure + returns (address[] makerAddresses) + { + uint256 orderArrayOffsetInBytes = orderArrayParamIndex * 32; + uint256 orderArrayPtr = uint256(loadExchangeData(orderArrayOffsetInBytes)); + uint256 orderArrayLength = uint256(loadExchangeData(orderArrayPtr)); + uint256 orderArrayLengthInBytes = orderArrayLength * 32; + uint256 orderArrayElementPtr = orderArrayPtr + 32; + uint256 orderArrayElementEndPtr = orderArrayElementPtr + orderArrayLengthInBytes; + for(uint orderPtrOffset = orderArrayElementPtr; orderPtrOffset < orderArrayElementEndPtr; orderPtrOffset += 32) { + uint256 orderPtr = uint256(loadExchangeData(orderPtrOffset)); + address makerAddress = address(loadExchangeData(orderPtr + orderArrayElementPtr)); + makerAddresses = makerAddresses.append(makerAddress); + } + return makerAddresses; + } +} diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IBalanceThresholdFilterCore.sol new file mode 100644 index 000000000..37e607be1 --- /dev/null +++ b/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IBalanceThresholdFilterCore.sol @@ -0,0 +1,56 @@ + +/* + + Copyright 2018 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.4.24; + + + +contract IBalanceThresholdFilterCore { + + /// @dev Executes an Exchange transaction iff the maker and taker meet + /// the hold at least `BALANCE_THRESHOLD` of the asset `THRESHOLD_ASSET` OR + /// the exchange function is a cancellation. + /// Supported Exchange functions: + /// - batchFillOrders + /// - batchFillOrdersNoThrow + /// - batchFillOrKillOrders + /// - fillOrder + /// - fillOrderNoThrow + /// - fillOrKillOrder + /// - marketBuyOrders + /// - marketBuyOrdersNoThrow + /// - marketSellOrders + /// - marketSellOrdersNoThrow + /// - matchOrders + /// - cancelOrder + /// - batchCancelOrders + /// - cancelOrdersUpTo + /// Trying to call any other exchange function will throw. + /// @param salt Arbitrary number to ensure uniqueness of transaction hash. + /// @param signerAddress Address of transaction signer. + /// @param signedExchangeTransaction AbiV2 encoded calldata. + /// @param signature Proof of signer transaction by signer. + function executeTransaction( + uint256 salt, + address signerAddress, + bytes signedExchangeTransaction, + bytes signature + ) + external; +} \ No newline at end of file diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol index 6aaa729fb..b8b67e6ee 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MBalanceThresholdFilterCore.sol @@ -20,9 +20,12 @@ pragma solidity 0.4.24; import "@0x/contracts-interfaces/contracts/protocol/Exchange/IExchange.sol"; import "../interfaces/IThresholdAsset.sol"; +import "../interfaces/IBalanceThresholdFilterCore.sol"; -contract MBalanceThresholdFilterCore { +contract MBalanceThresholdFilterCore is + IBalanceThresholdFilterCore +{ // Points to 0x exchange contract // solhint-disable var-name-mixedcase @@ -40,43 +43,12 @@ contract MBalanceThresholdFilterCore { address[] addresses ); - /// @dev Executes an Exchange transaction iff the maker and taker meet - /// the hold at least `BALANCE_THRESHOLD` of the asset `THRESHOLD_ASSET` OR - /// the exchange function is a cancellation. - /// Supported Exchange functions: - /// - batchFillOrders - /// - batchFillOrdersNoThrow - /// - batchFillOrKillOrders - /// - fillOrder - /// - fillOrderNoThrow - /// - fillOrKillOrder - /// - marketBuyOrders - /// - marketBuyOrdersNoThrow - /// - marketSellOrders - /// - marketSellOrdersNoThrow - /// - matchOrders - /// - cancelOrder - /// - batchCancelOrders - /// - cancelOrdersUpTo - /// Trying to call any other exchange function will throw. - /// @param salt Arbitrary number to ensure uniqueness of transaction hash. + /// @dev Constructs an array of addresses to be validated. + /// Addresses depend on which Exchange function is to be called + /// (defined by `signedExchangeTransaction` above). /// @param signerAddress Address of transaction signer. - /// @param signedExchangeTransaction AbiV2 encoded calldata. - /// @param signature Proof of signer transaction by signer. - function executeTransaction( - uint256 salt, - address signerAddress, - bytes signedExchangeTransaction, - bytes signature - ) - external; - - /// @dev Validates addresses meet the balance threshold specified by `BALANCE_THRESHOLD` - /// for the asset `THRESHOLD_ASSET`. If one address does not meet the thresold - /// then this function will revert. Which addresses are validated depends on - /// which Exchange function is to be called (defined by `signedExchangeTransaction` above). - /// No parameters are taken as this function reads arguments directly from calldata, to save gas. - /// If all addresses are valid then this function emits a ValidatedAddresses event, listing all - /// of the addresses whose balance thresholds it checked. - function validateBalanceThresholdsOrRevert(address signerAddress) internal; + /// @return addressesToValidate Array of addresses to validate. + function getAddressesToValidate(address signerAddress) + internal pure + returns (address[] memory addressesToValidate); } diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MExchangeCalldata.sol b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MExchangeCalldata.sol new file mode 100644 index 000000000..8e0414c17 --- /dev/null +++ b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MExchangeCalldata.sol @@ -0,0 +1,57 @@ + + /* + + Copyright 2018 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/LICENSE2.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.4.24; + + +contract MExchangeCalldata { + + /// @dev Emulates the `calldataload` opcode on the embedded Exchange calldata, + /// which is accessed through `signedExchangeTransaction`. + /// @param offset Offset into the Exchange calldata. + /// @return value Corresponding 32 byte value stored at `offset`. + function exchangeCalldataload(uint256 offset) + internal pure + returns (bytes32 value); + + /// @dev Convenience function that skips the 4 byte selector when loading + /// from the embedded Exchange calldata. + /// @param offset Offset into the Exchange calldata (minus the 4 byte selector) + /// @return value Corresponding 32 byte value stored at `offset` + 4. + function loadExchangeData(uint256 offset) + internal pure + returns (bytes32 value); + + /// @dev Extracts the maker address from an order stored in the Exchange calldata + /// (which is embedded in `signedExchangeTransaction`). + /// @param orderParamIndex Index of the order in the Exchange function's signature. + /// @return makerAddress The extracted maker address. + function loadMakerAddressFromOrder(uint256 orderParamIndex) + internal pure + returns (address makerAddress); + + /// @dev Extracts the maker addresses from an array of orders stored in the Exchange calldata + /// (which is embedded in `signedExchangeTransaction`), and records them in + /// the running list of addresses to validate. + /// @param orderArrayParamIndex Index of the order array in the Exchange function's signature + /// @return makerAddresses The extracted maker addresses. + function loadMakerAddressesFromOrderArray(uint256 orderArrayParamIndex) + internal pure + returns (address[] makerAddresses); +} -- cgit v1.2.3 From b524ac7af2ebf0f00c50ae3c1ad7cd85ab8b6462 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 13 Dec 2018 15:58:58 -0800 Subject: Prettier / Linter on contracts + TS --- .../MixinBalanceThresholdFilterCore.sol | 14 +-- .../MixinExchangeCalldata.sol | 5 +- .../interfaces/IBalanceThresholdFilterCore.sol | 3 +- .../mixins/MExchangeCalldata.sol | 3 +- .../test/extensions/balance_threshold_filter.ts | 109 ++++++--------------- 5 files changed, 44 insertions(+), 90 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index a8947751a..27767ad98 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -68,7 +68,7 @@ contract MixinBalanceThresholdFilterCore is // Validate account balances uint256 balanceThreshold = BALANCE_THRESHOLD; IThresholdAsset thresholdAsset = THRESHOLD_ASSET; - for(uint256 i = 0; i < addressesToValidate.length; ++i) { + for (uint256 i = 0; i < addressesToValidate.length; ++i) { uint256 addressBalance = thresholdAsset.balanceOf(addressesToValidate[i]); if (addressBalance < balanceThreshold) { revert("AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD"); @@ -95,8 +95,9 @@ contract MixinBalanceThresholdFilterCore is returns (address[] memory addressesToValidate) { bytes4 exchangeFunctionSelector = bytes4(exchangeCalldataload(0)); - if( - exchangeFunctionSelector == batchFillOrdersSelector || + // solhint-disable expression-indent + if ( + exchangeFunctionSelector == batchFillOrdersSelector || exchangeFunctionSelector == batchFillOrdersNoThrowSelector || exchangeFunctionSelector == batchFillOrKillOrdersSelector || exchangeFunctionSelector == marketBuyOrdersSelector || @@ -106,7 +107,7 @@ contract MixinBalanceThresholdFilterCore is ) { addressesToValidate = loadMakerAddressesFromOrderArray(0); addressesToValidate = addressesToValidate.append(signerAddress); - } else if( + } else if ( exchangeFunctionSelector == fillOrderSelector || exchangeFunctionSelector == fillOrderNoThrowSelector || exchangeFunctionSelector == fillOrKillOrderSelector @@ -114,18 +115,19 @@ contract MixinBalanceThresholdFilterCore is address makerAddress = loadMakerAddressFromOrder(0); addressesToValidate = addressesToValidate.append(makerAddress); addressesToValidate = addressesToValidate.append(signerAddress); - } else if(exchangeFunctionSelector == matchOrdersSelector) { + } else if (exchangeFunctionSelector == matchOrdersSelector) { address leftMakerAddress = loadMakerAddressFromOrder(0); addressesToValidate = addressesToValidate.append(leftMakerAddress); address rightMakerAddress = loadMakerAddressFromOrder(1); addressesToValidate = addressesToValidate.append(rightMakerAddress); addressesToValidate = addressesToValidate.append(signerAddress); - } else if( + } else if ( exchangeFunctionSelector != cancelOrderSelector && exchangeFunctionSelector != batchCancelOrdersSelector && exchangeFunctionSelector != cancelOrdersUpToSelector ) { revert("INVALID_OR_BLOCKED_EXCHANGE_SELECTOR"); } + // solhint-enable expression-indent } } diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol index 12f601dea..d49b7123f 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol @@ -78,8 +78,7 @@ contract MixinExchangeCalldata is } /// @dev Extracts the maker addresses from an array of orders stored in the Exchange calldata - /// (which is embedded in `signedExchangeTransaction`), and records them in - /// the running list of addresses to validate. + /// (which is embedded in `signedExchangeTransaction`). /// @param orderArrayParamIndex Index of the order array in the Exchange function's signature /// @return makerAddresses The extracted maker addresses. function loadMakerAddressesFromOrderArray(uint256 orderArrayParamIndex) @@ -92,7 +91,7 @@ contract MixinExchangeCalldata is uint256 orderArrayLengthInBytes = orderArrayLength * 32; uint256 orderArrayElementPtr = orderArrayPtr + 32; uint256 orderArrayElementEndPtr = orderArrayElementPtr + orderArrayLengthInBytes; - for(uint orderPtrOffset = orderArrayElementPtr; orderPtrOffset < orderArrayElementEndPtr; orderPtrOffset += 32) { + for (uint orderPtrOffset = orderArrayElementPtr; orderPtrOffset < orderArrayElementEndPtr; orderPtrOffset += 32) { uint256 orderPtr = uint256(loadExchangeData(orderPtrOffset)); address makerAddress = address(loadExchangeData(orderPtr + orderArrayElementPtr)); makerAddresses = makerAddresses.append(makerAddress); diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IBalanceThresholdFilterCore.sol index 37e607be1..3d8e2bbd1 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/interfaces/IBalanceThresholdFilterCore.sol @@ -20,7 +20,6 @@ pragma solidity 0.4.24; - contract IBalanceThresholdFilterCore { /// @dev Executes an Exchange transaction iff the maker and taker meet @@ -53,4 +52,4 @@ contract IBalanceThresholdFilterCore { bytes signature ) external; -} \ No newline at end of file +} diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MExchangeCalldata.sol b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MExchangeCalldata.sol index 8e0414c17..bf2940fe1 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MExchangeCalldata.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/mixins/MExchangeCalldata.sol @@ -47,8 +47,7 @@ contract MExchangeCalldata { returns (address makerAddress); /// @dev Extracts the maker addresses from an array of orders stored in the Exchange calldata - /// (which is embedded in `signedExchangeTransaction`), and records them in - /// the running list of addresses to validate. + /// (which is embedded in `signedExchangeTransaction`). /// @param orderArrayParamIndex Index of the order array in the Exchange function's signature /// @return makerAddresses The extracted maker addresses. function loadMakerAddressesFromOrderArray(uint256 orderArrayParamIndex) diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts index 6350c019f..20397b14f 100644 --- a/contracts/extensions/test/extensions/balance_threshold_filter.ts +++ b/contracts/extensions/test/extensions/balance_threshold_filter.ts @@ -5,7 +5,6 @@ import { BigNumber } from '@0x/utils'; import { Web3Wrapper } from '@0x/web3-wrapper'; import * as chai from 'chai'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; import * as _ from 'lodash'; import { @@ -21,12 +20,9 @@ import { ContractName, ERC20BalancesByOwner, expectTransactionFailedAsync, - expectTransactionFailedWithoutReasonAsync, OrderFactory, OrderStatus, - orderUtils, provider, - SignedTransaction, TransactionFactory, txDefaults, web3Wrapper, @@ -77,7 +73,6 @@ describe(ContractName.BalanceThresholdFilter, () => { let defaultOrderParams: Partial; let validSignedOrder: SignedOrder; let validSignedOrder2: SignedOrder; - let validSignedFillOrderTx: SignedTransaction; let erc721BalanceThresholdFilterInstance: BalanceThresholdFilterContract; let erc20BalanceThresholdFilterInstance: BalanceThresholdFilterContract; @@ -257,10 +252,7 @@ describe(ContractName.BalanceThresholdFilter, () => { { takerAssetFillAmount }, ); // Assert validated addresses - const expectedValidatedAddresseses = [ - validSignedOrder.makerAddress, - validTakerAddress, - ]; + const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -308,7 +300,7 @@ describe(ContractName.BalanceThresholdFilter, () => { badSelectorHex, signatureHex, ), - RevertReason.InvalidOrBlockedExchangeSelector + RevertReason.InvalidOrBlockedExchangeSelector, ); }); it('should revert if senderAddress is not set to the valid forwarding contract', async () => { @@ -319,12 +311,10 @@ describe(ContractName.BalanceThresholdFilter, () => { }); // Call valid forwarder return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.fillOrderAsync( - signedOrderWithBadSenderAddress, - validTakerAddress, - { takerAssetFillAmount }, - ), - RevertReason.FailedExecution + erc721TakerBalanceThresholdWrapper.fillOrderAsync(signedOrderWithBadSenderAddress, validTakerAddress, { + takerAssetFillAmount, + }), + RevertReason.FailedExecution, ); }); }); @@ -339,11 +329,9 @@ describe(ContractName.BalanceThresholdFilter, () => { // Execute a valid fill const orders = [validSignedOrder, validSignedOrder2]; const takerAssetFillAmounts = [takerAssetFillAmount, takerAssetFillAmount]; - const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync( - orders, - validTakerAddress, - { takerAssetFillAmounts }, - ); + const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersAsync(orders, validTakerAddress, { + takerAssetFillAmounts, + }); // Assert validated addresses const expectedValidatedAddresseses = [ validSignedOrder.makerAddress, @@ -647,10 +635,7 @@ describe(ContractName.BalanceThresholdFilter, () => { { takerAssetFillAmount }, ); // Assert validated addresses - const expectedValidatedAddresseses = [ - validSignedOrder.makerAddress, - validTakerAddress, - ]; + const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -693,11 +678,9 @@ describe(ContractName.BalanceThresholdFilter, () => { }); // Execute transaction return expectTransactionFailedAsync( - erc721TakerBalanceThresholdWrapper.fillOrderAsync( - signedOrderWithBadMakerAddress, - validTakerAddress, - { takerAssetFillAmount }, - ), + erc721TakerBalanceThresholdWrapper.fillOrderAsync(signedOrderWithBadMakerAddress, validTakerAddress, { + takerAssetFillAmount, + }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); @@ -724,10 +707,7 @@ describe(ContractName.BalanceThresholdFilter, () => { { takerAssetFillAmount }, ); // Assert validated addresses - const expectedValidatedAddresseses = [ - validSignedOrder.makerAddress, - validTakerAddress, - ]; + const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -780,11 +760,9 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( - erc721NonValidBalanceThresholdWrapper.fillOrderNoThrowAsync( - validSignedOrder, - invalidAddress, - { takerAssetFillAmount }, - ), + erc721NonValidBalanceThresholdWrapper.fillOrderNoThrowAsync(validSignedOrder, invalidAddress, { + takerAssetFillAmount, + }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); @@ -804,10 +782,7 @@ describe(ContractName.BalanceThresholdFilter, () => { { takerAssetFillAmount: takerAssetFillAmount_ }, ); // Assert validated addresses - const expectedValidatedAddresseses = [ - validSignedOrder.makerAddress, - validTakerAddress, - ]; + const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress]; await assertValidatedAddressesLog(txReceipt, expectedValidatedAddresseses); // Check balances const newBalances = await erc20Wrapper.getBalancesAsync(); @@ -860,11 +835,9 @@ describe(ContractName.BalanceThresholdFilter, () => { }); it('should revert if taker does not meet the balance threshold', async () => { return expectTransactionFailedAsync( - erc721NonValidBalanceThresholdWrapper.fillOrKillOrderAsync( - validSignedOrder, - invalidAddress, - { takerAssetFillAmount }, - ), + erc721NonValidBalanceThresholdWrapper.fillOrKillOrderAsync(validSignedOrder, invalidAddress, { + takerAssetFillAmount, + }), RevertReason.AtLeastOneAddressDoesNotMeetBalanceThreshold, ); }); @@ -916,14 +889,10 @@ describe(ContractName.BalanceThresholdFilter, () => { const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); // Maker #1 expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus( - validSignedOrder.makerAssetAmount, - ), + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(validSignedOrder.makerAssetAmount), ); expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[validMakerAddress][defaultTakerAssetAddress].add( - validSignedOrder.takerAssetAmount, - ), + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(validSignedOrder.takerAssetAmount), ); expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee), @@ -1018,14 +987,10 @@ describe(ContractName.BalanceThresholdFilter, () => { const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); // Maker #1 expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus( - validSignedOrder.makerAssetAmount, - ), + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(validSignedOrder.makerAssetAmount), ); expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[validMakerAddress][defaultTakerAssetAddress].add( - validSignedOrder.takerAssetAmount, - ), + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(validSignedOrder.takerAssetAmount), ); expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee), @@ -1097,11 +1062,9 @@ describe(ContractName.BalanceThresholdFilter, () => { .times(validSignedOrder.makerAssetAmount) .dividedToIntegerBy(validSignedOrder.takerAssetAmount); const cumulativeMakerAssetFillAmount = validSignedOrder.makerAssetAmount.plus(makerAssetFillAmount2); - const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync( - orders, - validTakerAddress, - { makerAssetFillAmount: cumulativeMakerAssetFillAmount }, - ); + const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersAsync(orders, validTakerAddress, { + makerAssetFillAmount: cumulativeMakerAssetFillAmount, + }); // Assert validated addresses const expectedValidatedAddresseses = [ validSignedOrder.makerAddress, @@ -1120,14 +1083,10 @@ describe(ContractName.BalanceThresholdFilter, () => { const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2); // Maker #1 expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus( - validSignedOrder.makerAssetAmount, - ), + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(validSignedOrder.makerAssetAmount), ); expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[validMakerAddress][defaultTakerAssetAddress].add( - validSignedOrder.takerAssetAmount, - ), + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(validSignedOrder.takerAssetAmount), ); expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee), @@ -1224,14 +1183,10 @@ describe(ContractName.BalanceThresholdFilter, () => { const takerFeePaid = validSignedOrder.takerFee.plus(takerFeePaid2); // Maker #1 expect(newBalances[validMakerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus( - validSignedOrder.makerAssetAmount, - ), + erc20Balances[validMakerAddress][defaultMakerAssetAddress].minus(validSignedOrder.makerAssetAmount), ); expect(newBalances[validMakerAddress][defaultTakerAssetAddress]).to.be.bignumber.equal( - erc20Balances[validMakerAddress][defaultTakerAssetAddress].add( - validSignedOrder.takerAssetAmount, - ), + erc20Balances[validMakerAddress][defaultTakerAssetAddress].add(validSignedOrder.takerAssetAmount), ); expect(newBalances[validMakerAddress][zrxToken.address]).to.be.bignumber.equal( erc20Balances[validMakerAddress][zrxToken.address].minus(validSignedOrder.makerFee), -- cgit v1.2.3 From bb4ce9b3ad5658b16027c53cb4bad07149dcff4e Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 13 Dec 2018 16:02:13 -0800 Subject: Explicit returns --- .../BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol | 1 + .../contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol | 2 ++ 2 files changed, 3 insertions(+) (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index 27767ad98..3e292c035 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -129,5 +129,6 @@ contract MixinBalanceThresholdFilterCore is revert("INVALID_OR_BLOCKED_EXCHANGE_SELECTOR"); } // solhint-enable expression-indent + return addressesToValidate; } } diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol index d49b7123f..bd26a468f 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinExchangeCalldata.sol @@ -50,6 +50,7 @@ contract MixinExchangeCalldata is let exchangeCalldataOffset := add(exchangeTxPtr, add(0x24, offset)) value := calldataload(exchangeCalldataOffset) } + return value; } /// @dev Convenience function that skips the 4 byte selector when loading @@ -61,6 +62,7 @@ contract MixinExchangeCalldata is returns (bytes32 value) { value = exchangeCalldataload(offset + 4); + return value; } /// @dev Extracts the maker address from an order stored in the Exchange calldata -- cgit v1.2.3 From 25722d81549382617df1c70e833748782ad3e3ac Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 13 Dec 2018 16:10:40 -0800 Subject: Updated comment `Execute fillOrder` -> `Execute exchange function` --- .../BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index 3e292c035..2917403bd 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -76,7 +76,7 @@ contract MixinBalanceThresholdFilterCore is } emit ValidatedAddresses(addressesToValidate); - // All addresses are valid. Execute fillOrder. + // All addresses are valid. Execute exchange function. EXCHANGE.executeTransaction( salt, signerAddress, -- cgit v1.2.3 From 1de92659ee5d3cad687919bd3054d24e31461bfa Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 13 Dec 2018 18:07:29 -0800 Subject: Added Changelog for new Extensions --- contracts/extensions/CHANGELOG.json | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'contracts/extensions') diff --git a/contracts/extensions/CHANGELOG.json b/contracts/extensions/CHANGELOG.json index 19ac770af..99bc0265e 100644 --- a/contracts/extensions/CHANGELOG.json +++ b/contracts/extensions/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "timestamp": 1544753227, + "version": "1.0.3", + "changes": [ + { + "note": "Added Balance Threshold Filter" + } + ] + }, { "timestamp": 1544741676, "version": "1.0.2", -- cgit v1.2.3 From 00f5b94d0a585ccf4b1df4c9bddb4c19eb86cfe2 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 14 Dec 2018 11:22:52 -0800 Subject: Added `gas` field so tests pass on Geth; --- .../test/extensions/balance_threshold_filter.ts | 36 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/test/extensions/balance_threshold_filter.ts b/contracts/extensions/test/extensions/balance_threshold_filter.ts index 20397b14f..07199d60b 100644 --- a/contracts/extensions/test/extensions/balance_threshold_filter.ts +++ b/contracts/extensions/test/extensions/balance_threshold_filter.ts @@ -428,7 +428,13 @@ describe(ContractName.BalanceThresholdFilter, () => { const txReceipt = await erc721TakerBalanceThresholdWrapper.batchFillOrdersNoThrowAsync( orders, validTakerAddress, - { takerAssetFillAmounts }, + { + takerAssetFillAmounts, + // HACK(albrow): We need to hardcode the gas estimate here because + // the Geth gas estimator doesn't work with the way we use + // delegatecall and swallow errors. + gas: 600000, + }, ); // Assert validated addresses const expectedValidatedAddresseses = [ @@ -704,7 +710,13 @@ describe(ContractName.BalanceThresholdFilter, () => { const txReceipt = await erc721TakerBalanceThresholdWrapper.fillOrderNoThrowAsync( validSignedOrder, validTakerAddress, - { takerAssetFillAmount }, + { + takerAssetFillAmount, + // HACK(albrow): We need to hardcode the gas estimate here because + // the Geth gas estimator doesn't work with the way we use + // delegatecall and swallow errors. + gas: 600000, + }, ); // Assert validated addresses const expectedValidatedAddresseses = [validSignedOrder.makerAddress, validTakerAddress]; @@ -963,7 +975,13 @@ describe(ContractName.BalanceThresholdFilter, () => { const txReceipt = await erc721TakerBalanceThresholdWrapper.marketSellOrdersNoThrowAsync( orders, validTakerAddress, - { takerAssetFillAmount: cumulativeTakerAssetFillAmount }, + { + takerAssetFillAmount: cumulativeTakerAssetFillAmount, + // HACK(albrow): We need to hardcode the gas estimate here because + // the Geth gas estimator doesn't work with the way we use + // delegatecall and swallow errors. + gas: 600000, + }, ); // Assert validated addresses const expectedValidatedAddresseses = [ @@ -1163,7 +1181,13 @@ describe(ContractName.BalanceThresholdFilter, () => { const txReceipt = await erc721TakerBalanceThresholdWrapper.marketBuyOrdersNoThrowAsync( orders, validTakerAddress, - { makerAssetFillAmount: cumulativeMakerAssetFillAmount }, + { + makerAssetFillAmount: cumulativeMakerAssetFillAmount, + // HACK(albrow): We need to hardcode the gas estimate here because + // the Geth gas estimator doesn't work with the way we use + // delegatecall and swallow errors. + gas: 600000, + }, ); // Assert validated addresses const expectedValidatedAddresseses = [ @@ -1493,7 +1517,7 @@ describe(ContractName.BalanceThresholdFilter, () => { // Cancel const txReceipt = await erc721MakerBalanceThresholdWrapper.batchCancelOrdersAsync( validSignedOrders, - validSignedOrder.makerAddress, + validSignedOrders[0].makerAddress, ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; @@ -1560,7 +1584,7 @@ describe(ContractName.BalanceThresholdFilter, () => { const cancelOrdersUpToThisSalt = new BigNumber(1); const txReceipt = await erc721MakerBalanceThresholdWrapper.cancelOrdersUpToAsync( cancelOrdersUpToThisSalt, - validSignedOrder.makerAddress, + validSignedOrders[0].makerAddress, ); // Assert validated addresses const expectedValidatedAddresseses: string[] = []; -- cgit v1.2.3 From afe200c4e1bd76d5f2dbfcb7898ca025a7bb3dd6 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Fri, 14 Dec 2018 11:26:38 -0800 Subject: Updated changelogs for new contracts --- contracts/extensions/CHANGELOG.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/CHANGELOG.json b/contracts/extensions/CHANGELOG.json index 99bc0265e..da4d9c2ba 100644 --- a/contracts/extensions/CHANGELOG.json +++ b/contracts/extensions/CHANGELOG.json @@ -1,10 +1,10 @@ [ { - "timestamp": 1544753227, - "version": "1.0.3", + "version": "1.1.0", "changes": [ { - "note": "Added Balance Threshold Filter" + "note": "Added Balance Threshold Filter", + "pr": 1383 } ] }, -- cgit v1.2.3 From d2a4fd570622de34a3d8e8a25735b025e3ac5f77 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 18 Dec 2018 11:36:05 -0800 Subject: Added documentation to `LibAddressArray.append` and switched `if` to `require` smt --- .../BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index 2917403bd..ab6989115 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -70,9 +70,10 @@ contract MixinBalanceThresholdFilterCore is IThresholdAsset thresholdAsset = THRESHOLD_ASSET; for (uint256 i = 0; i < addressesToValidate.length; ++i) { uint256 addressBalance = thresholdAsset.balanceOf(addressesToValidate[i]); - if (addressBalance < balanceThreshold) { - revert("AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD"); - } + require( + addressBalance >= balanceThreshold, + "AT_LEAST_ONE_ADDRESS_DOES_NOT_MEET_BALANCE_THRESHOLD" + ); } emit ValidatedAddresses(addressesToValidate); -- cgit v1.2.3 From ca0ab385218d588aee10502e3d75ade30ad0b5d7 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 18 Dec 2018 11:53:41 -0800 Subject: Fixed solhint errors --- .../MixinBalanceThresholdFilterCore.sol | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'contracts/extensions') diff --git a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol index ab6989115..df830f36e 100644 --- a/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol +++ b/contracts/extensions/contracts/BalanceThresholdFilter/MixinBalanceThresholdFilterCore.sol @@ -98,34 +98,34 @@ contract MixinBalanceThresholdFilterCore is bytes4 exchangeFunctionSelector = bytes4(exchangeCalldataload(0)); // solhint-disable expression-indent if ( - exchangeFunctionSelector == batchFillOrdersSelector || - exchangeFunctionSelector == batchFillOrdersNoThrowSelector || - exchangeFunctionSelector == batchFillOrKillOrdersSelector || - exchangeFunctionSelector == marketBuyOrdersSelector || - exchangeFunctionSelector == marketBuyOrdersNoThrowSelector || - exchangeFunctionSelector == marketSellOrdersSelector || - exchangeFunctionSelector == marketSellOrdersNoThrowSelector + exchangeFunctionSelector == BATCH_FILL_ORDERS_SELECTOR || + exchangeFunctionSelector == BATCH_FILL_ORDERS_NO_THROW_SELECTOR || + exchangeFunctionSelector == BATCH_FILL_OR_KILL_ORDERS_SELECTOR || + exchangeFunctionSelector == MARKET_BUY_ORDERS_SELECTOR || + exchangeFunctionSelector == MARKET_BUY_ORDERS_NO_THROW_SELECTOR || + exchangeFunctionSelector == MARKET_SELL_ORDERS_SELECTOR || + exchangeFunctionSelector == MARKET_SELL_ORDERS_NO_THROW_SELECTOR ) { addressesToValidate = loadMakerAddressesFromOrderArray(0); addressesToValidate = addressesToValidate.append(signerAddress); } else if ( - exchangeFunctionSelector == fillOrderSelector || - exchangeFunctionSelector == fillOrderNoThrowSelector || - exchangeFunctionSelector == fillOrKillOrderSelector + exchangeFunctionSelector == FILL_ORDER_SELECTOR || + exchangeFunctionSelector == FILL_ORDER_NO_THROW_SELECTOR || + exchangeFunctionSelector == FILL_OR_KILL_ORDER_SELECTOR ) { address makerAddress = loadMakerAddressFromOrder(0); addressesToValidate = addressesToValidate.append(makerAddress); addressesToValidate = addressesToValidate.append(signerAddress); - } else if (exchangeFunctionSelector == matchOrdersSelector) { + } else if (exchangeFunctionSelector == MATCH_ORDERS_SELECTOR) { address leftMakerAddress = loadMakerAddressFromOrder(0); addressesToValidate = addressesToValidate.append(leftMakerAddress); address rightMakerAddress = loadMakerAddressFromOrder(1); addressesToValidate = addressesToValidate.append(rightMakerAddress); addressesToValidate = addressesToValidate.append(signerAddress); } else if ( - exchangeFunctionSelector != cancelOrderSelector && - exchangeFunctionSelector != batchCancelOrdersSelector && - exchangeFunctionSelector != cancelOrdersUpToSelector + exchangeFunctionSelector != CANCEL_ORDER_SELECTOR && + exchangeFunctionSelector != BATCH_CANCEL_ORDERS_SELECTOR && + exchangeFunctionSelector != CANCEL_ORDERS_UP_TO_SELECTOR ) { revert("INVALID_OR_BLOCKED_EXCHANGE_SELECTOR"); } -- cgit v1.2.3