aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2018-04-27 00:29:05 +0800
committerAmir Bandeali <abandeali1@gmail.com>2018-04-27 02:11:54 +0800
commit599d34f1c08c3b41817c8cfe3f4e1b847cda072b (patch)
tree6c3299c43de6c5036f6e0d20ab6c15ff14988333
parent31411dd11be29d5dcca646737e6ca08840e2d510 (diff)
downloaddexon-sol-tools-599d34f1c08c3b41817c8cfe3f4e1b847cda072b.tar
dexon-sol-tools-599d34f1c08c3b41817c8cfe3f4e1b847cda072b.tar.gz
dexon-sol-tools-599d34f1c08c3b41817c8cfe3f4e1b847cda072b.tar.bz2
dexon-sol-tools-599d34f1c08c3b41817c8cfe3f4e1b847cda072b.tar.lz
dexon-sol-tools-599d34f1c08c3b41817c8cfe3f4e1b847cda072b.tar.xz
dexon-sol-tools-599d34f1c08c3b41817c8cfe3f4e1b847cda072b.tar.zst
dexon-sol-tools-599d34f1c08c3b41817c8cfe3f4e1b847cda072b.zip
Make all lib functions internal, add contracts for testing
-rw-r--r--packages/contracts/package.json4
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol2
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol5
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol71
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol5
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol3
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol28
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol9
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol8
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol6
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol3
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol3
-rw-r--r--packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol80
-rw-r--r--packages/contracts/src/contracts/current/test/TestSignatureValidator/TestSignatureValidator.sol (renamed from packages/contracts/src/contracts/current/protocol/Exchange/LibPartialAmount.sol)33
-rw-r--r--packages/contracts/src/utils/exchange_wrapper.ts31
-rw-r--r--packages/contracts/src/utils/types.ts2
-rw-r--r--packages/contracts/test/exchange/helpers.ts178
-rw-r--r--packages/contracts/test/exchange/libs.ts155
-rw-r--r--packages/contracts/test/exchange/signature_validator.ts93
19 files changed, 448 insertions, 271 deletions
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 51850ec69..410735359 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -30,9 +30,9 @@
},
"config": {
"abis":
- "../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|ERC20Proxy|ERC721Proxy|DummyERC721Token|LibBytes|Authorizable).json",
+ "../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|LibBytes|Authorizable).json",
"contracts":
- "Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,ERC20Proxy,ERC721Proxy,DummyERC721Token,LibBytes,Authorizable"
+ "Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,LibBytes,Authorizable"
},
"repository": {
"type": "git",
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
index 47f9e7a4d..e78446b99 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
@@ -29,8 +29,8 @@ import "./MixinTransactions.sol";
contract Exchange is
MixinWrapperFunctions,
MixinExchangeCore,
- MixinSignatureValidator,
MixinSettlement,
+ MixinSignatureValidator,
MixinTransactions,
MixinAssetProxyDispatcher
{
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol b/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol
index de3989a96..d5641a09f 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol
@@ -23,7 +23,8 @@ contract ISigner {
function isValidSignature(
bytes32 hash,
- bytes memory signature)
- public view
+ bytes signature)
+ external
+ view
returns (bool isValid);
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol
new file mode 100644
index 000000000..3b553ebbc
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/LibMath.sol
@@ -0,0 +1,71 @@
+/*
+
+ 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.21;
+pragma experimental ABIEncoderV2;
+
+import "../../utils/SafeMath/SafeMath.sol";
+
+contract LibMath is SafeMath {
+
+ /// @dev Calculates partial value given a numerator and denominator.
+ /// @param numerator Numerator.
+ /// @param denominator Denominator.
+ /// @param target Value to calculate partial of.
+ /// @return Partial value of target.
+ function getPartialAmount(
+ uint256 numerator,
+ uint256 denominator,
+ uint256 target)
+ internal
+ pure
+ returns (uint256 partialAmount)
+ {
+ partialAmount = safeDiv(
+ safeMul(numerator, target),
+ denominator
+ );
+ return partialAmount;
+ }
+
+ /// @dev Checks if rounding error > 0.1%.
+ /// @param numerator Numerator.
+ /// @param denominator Denominator.
+ /// @param target Value to multiply with numerator/denominator.
+ /// @return Rounding error is present.
+ function isRoundingError(
+ uint256 numerator,
+ uint256 denominator,
+ uint256 target)
+ internal
+ pure
+ returns (bool isError)
+ {
+ uint256 remainder = mulmod(target, numerator, denominator);
+ if (remainder == 0) {
+ return false; // No rounding error.
+ }
+
+ uint256 errPercentageTimes1000000 = safeDiv(
+ safeMul(remainder, 1000000),
+ safeMul(numerator, target)
+ );
+ isError = errPercentageTimes1000000 > 1000;
+ return isError;
+ }
+}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol
index a98d7cbeb..df974e177 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/LibOrder.sol
@@ -55,8 +55,9 @@ contract LibOrder {
/// @dev Calculates Keccak-256 hash of the order.
/// @param order The order structure.
/// @return Keccak-256 EIP712 hash of the order.
- function getOrderHash(Order order)
- public view
+ function getOrderHash(Order memory order)
+ internal
+ view
returns (bytes32 orderHash)
{
// TODO: EIP712 is not finalized yet
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
index b60a1cb08..b03bf464a 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
@@ -78,7 +78,8 @@ contract MixinAssetProxyDispatcher is
/// @param assetProxyId Id of the asset proxy.
/// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
function getAssetProxy(uint8 assetProxyId)
- external view
+ external
+ view
returns (address)
{
IAssetProxy assetProxy = assetProxies[assetProxyId];
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
index af114930b..4ca271b2a 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
@@ -19,11 +19,10 @@
pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
-import "../../utils/SafeMath/SafeMath.sol";
import "./LibFillResults.sol";
import "./LibOrder.sol";
import "./LibErrors.sol";
-import "./LibPartialAmount.sol";
+import "./LibMath.sol";
import "./mixins/MExchangeCore.sol";
import "./mixins/MSettlement.sol";
import "./mixins/MSignatureValidator.sol";
@@ -33,11 +32,10 @@ import "./mixins/MTransactions.sol";
/// @dev Consumes MSettlement
/// @dev Consumes MSignatureValidator
contract MixinExchangeCore is
- SafeMath,
LibOrder,
LibFillResults,
LibErrors,
- LibPartialAmount,
+ LibMath,
MExchangeCore,
MSettlement,
MSignatureValidator,
@@ -219,28 +217,6 @@ contract MixinExchangeCore is
emit CancelUpTo(msg.sender, newMakerEpoch);
}
- /// @dev Checks if rounding error > 0.1%.
- /// @param numerator Numerator.
- /// @param denominator Denominator.
- /// @param target Value to multiply with numerator/denominator.
- /// @return Rounding error is present.
- function isRoundingError(uint256 numerator, uint256 denominator, uint256 target)
- public pure
- returns (bool isError)
- {
- uint256 remainder = mulmod(target, numerator, denominator);
- if (remainder == 0) {
- return false; // No rounding error.
- }
-
- uint256 errPercentageTimes1000000 = safeDiv(
- safeMul(remainder, 1000000),
- safeMul(numerator, target)
- );
- isError = errPercentageTimes1000000 > 1000;
- return isError;
- }
-
/// @dev Logs a Fill event with the given arguments.
/// The sole purpose of this function is to get around the stack variable limit.
function emitFillEvent(
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
index df86a9dfa..cab2ccfb6 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
@@ -22,19 +22,20 @@ pragma experimental ABIEncoderV2;
import "./mixins/MSettlement.sol";
import "./mixins/MAssetProxyDispatcher.sol";
import "./LibOrder.sol";
-import "./LibPartialAmount.sol";
+import "./LibMath.sol";
import "../AssetProxy/IAssetProxy.sol";
/// @dev Provides MixinSettlement
contract MixinSettlement is
- LibPartialAmount,
+ LibMath,
MSettlement,
MAssetProxyDispatcher
{
- bytes ZRX_PROXY_DATA;
+ bytes internal ZRX_PROXY_DATA;
function zrxProxyData()
- external view
+ external
+ view
returns (bytes memory)
{
return ZRX_PROXY_DATA;
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
index 46bf01e78..690a70820 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
@@ -24,6 +24,7 @@ import "./ISigner.sol";
/// @dev Provides MSignatureValidator
contract MixinSignatureValidator is MSignatureValidator {
+
enum SignatureType {
Illegal, // Default value
Invalid,
@@ -47,7 +48,8 @@ contract MixinSignatureValidator is MSignatureValidator {
bytes32 hash,
address signer,
bytes memory signature)
- public view
+ internal
+ view
returns (bool isValid)
{
// TODO: Domain separation: make hash depend on role. (Taker sig should not be valid as maker sig, etc.)
@@ -164,8 +166,8 @@ contract MixinSignatureValidator is MSignatureValidator {
function preSign(
bytes32 hash,
address signer,
- bytes memory signature)
- public
+ bytes signature)
+ external
{
require(isValidSignature(hash, signer, signature));
preSigned[hash][signer] = true;
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
index fe58e3d18..105c0f0a0 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
@@ -19,19 +19,17 @@
pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
-import "../../utils/SafeMath/SafeMath.sol";
import "../../utils/LibBytes/LibBytes.sol";
import "./mixins/MExchangeCore.sol";
-import "./LibPartialAmount.sol";
+import "./LibMath.sol";
import "./LibOrder.sol";
import "./LibFillResults.sol";
/// @dev Consumes MExchangeCore
contract MixinWrapperFunctions is
- SafeMath,
LibOrder,
LibFillResults,
- LibPartialAmount,
+ LibMath,
LibBytes,
MExchangeCore
{
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
index a46be9d0f..6d0a3cd38 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
@@ -55,6 +55,7 @@ contract MAssetProxyDispatcher {
/// @param assetProxyId Id of the asset proxy.
/// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
function getAssetProxy(uint8 assetProxyId)
- external view
+ external
+ view
returns (address);
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol
index 3f020e0a4..043a7da9c 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol
@@ -30,6 +30,7 @@ contract MSignatureValidator {
bytes32 hash,
address signer,
bytes memory signature)
- public view
+ internal
+ view
returns (bool isValid);
}
diff --git a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol
new file mode 100644
index 000000000..a5b327a90
--- /dev/null
+++ b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol
@@ -0,0 +1,80 @@
+/*
+
+ 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.21;
+pragma experimental ABIEncoderV2;
+
+import "../../protocol/Exchange/LibMath.sol";
+import "../../protocol/Exchange/LibOrder.sol";
+import "../../protocol/Exchange/LibFillResults.sol";
+
+contract TestLibs is
+ LibMath,
+ LibOrder,
+ LibFillResults
+{
+ function publicGetPartialAmount(
+ uint256 numerator,
+ uint256 denominator,
+ uint256 target)
+ public
+ pure
+ returns (uint256 partialAmount)
+ {
+ partialAmount = getPartialAmount(
+ numerator,
+ denominator,
+ target
+ );
+ return partialAmount;
+ }
+
+ function publicIsRoundingError(
+ uint256 numerator,
+ uint256 denominator,
+ uint256 target)
+ public
+ pure
+ returns (bool isError)
+ {
+ isError = isRoundingError(
+ numerator,
+ denominator,
+ target
+ );
+ return isError;
+ }
+
+ function publicGetOrderHash(Order memory order)
+ public
+ view
+ returns (bytes32 orderHash)
+ {
+ orderHash = getOrderHash(order);
+ return orderHash;
+ }
+
+ function publicAddFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults)
+ public
+ pure
+ returns (FillResults memory)
+ {
+ addFillResults(totalFillResults, singleFillResults);
+ return totalFillResults;
+ }
+} \ No newline at end of file
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/LibPartialAmount.sol b/packages/contracts/src/contracts/current/test/TestSignatureValidator/TestSignatureValidator.sol
index 2ff244e98..4ba04b64e 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/LibPartialAmount.sol
+++ b/packages/contracts/src/contracts/current/test/TestSignatureValidator/TestSignatureValidator.sol
@@ -19,20 +19,23 @@
pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
-import "../../utils/SafeMath/SafeMath.sol";
-
-contract LibPartialAmount is SafeMath {
-
- /// @dev Calculates partial value given a numerator and denominator.
- /// @param numerator Numerator.
- /// @param denominator Denominator.
- /// @param target Value to calculate partial of.
- /// @return Partial value of target.
- function getPartialAmount(uint256 numerator, uint256 denominator, uint256 target)
- public pure
- returns (uint256 partialAmount)
+import "../../protocol/Exchange/MixinSignatureValidator.sol";
+
+contract TestSignatureValidator is MixinSignatureValidator {
+
+ function publicIsValidSignature(
+ bytes32 hash,
+ address signer,
+ bytes memory signature)
+ public
+ view
+ returns (bool isValid)
{
- partialAmount = safeDiv(safeMul(numerator, target), denominator);
- return partialAmount;
+ isValid = isValidSignature(
+ hash,
+ signer,
+ signature
+ );
+ return isValid;
}
-}
+} \ No newline at end of file
diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts
index 000905854..27fdd698f 100644
--- a/packages/contracts/src/utils/exchange_wrapper.ts
+++ b/packages/contracts/src/utils/exchange_wrapper.ts
@@ -221,37 +221,6 @@ export class ExchangeWrapper {
const tx = await this._getTxWithDecodedExchangeLogsAsync(txHash);
return tx;
}
- public async getOrderHashAsync(signedOrder: SignedOrder): Promise<string> {
- const order = orderUtils.getOrderStruct(signedOrder);
- const orderHash = await this._exchange.getOrderHash.callAsync(order);
- return orderHash;
- }
- public async isValidSignatureAsync(signedOrder: SignedOrder): Promise<boolean> {
- const isValidSignature = await this._exchange.isValidSignature.callAsync(
- orderUtils.getOrderHashHex(signedOrder),
- signedOrder.makerAddress,
- signedOrder.signature,
- );
- return isValidSignature;
- }
- public async isRoundingErrorAsync(
- numerator: BigNumber,
- denominator: BigNumber,
- target: BigNumber,
- ): Promise<boolean> {
- const isRoundingError = await this._exchange.isRoundingError.callAsync(numerator, denominator, target);
- return isRoundingError;
- }
- public async getPartialAmountAsync(
- numerator: BigNumber,
- denominator: BigNumber,
- target: BigNumber,
- ): Promise<BigNumber> {
- const partialAmount = new BigNumber(
- await this._exchange.getPartialAmount.callAsync(numerator, denominator, target),
- );
- return partialAmount;
- }
public async getTakerAssetFilledAmountAsync(orderHashHex: string): Promise<BigNumber> {
const filledAmount = new BigNumber(await this._exchange.filled.callAsync(orderHashHex));
return filledAmount;
diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts
index 934dc52fa..6f9aeda94 100644
--- a/packages/contracts/src/utils/types.ts
+++ b/packages/contracts/src/utils/types.ts
@@ -94,6 +94,8 @@ export enum ContractName {
EtherDelta = 'EtherDelta',
Arbitrage = 'Arbitrage',
TestAssetProxyDispatcher = 'TestAssetProxyDispatcher',
+ TestLibs = 'TestLibs',
+ TestSignatureValidator = 'TestSignatureValidator',
ERC20Proxy = 'ERC20Proxy',
ERC721Proxy = 'ERC721Proxy',
DummyERC721Token = 'DummyERC721Token',
diff --git a/packages/contracts/test/exchange/helpers.ts b/packages/contracts/test/exchange/helpers.ts
deleted file mode 100644
index f986665ff..000000000
--- a/packages/contracts/test/exchange/helpers.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-import { ZeroEx } from '0x.js';
-import { BlockchainLifecycle } from '@0xproject/dev-utils';
-import { BigNumber } from '@0xproject/utils';
-import * as chai from 'chai';
-import ethUtil = require('ethereumjs-util');
-
-import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
-import { addressUtils } from '../../src/utils/address_utils';
-import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
-import { constants } from '../../src/utils/constants';
-import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
-import { OrderFactory } from '../../src/utils/order_factory';
-import { orderUtils } from '../../src/utils/order_utils';
-import { AssetProxyId, ContractName, SignedOrder } from '../../src/utils/types';
-import { chaiSetup } from '../utils/chai_setup';
-import { deployer } from '../utils/deployer';
-import { provider, web3Wrapper } from '../utils/web3_wrapper';
-
-chaiSetup.configure();
-const expect = chai.expect;
-
-const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
-
-describe('Exchange helpers', () => {
- let signedOrder: SignedOrder;
- let exchangeWrapper: ExchangeWrapper;
- let orderFactory: OrderFactory;
-
- before(async () => {
- const accounts = await web3Wrapper.getAvailableAddressesAsync();
- const makerAddress = accounts[0];
- const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [AssetProxyId.ERC20]);
- const exchange = new ExchangeContract(exchangeInstance.abi, exchangeInstance.address, provider);
- const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID });
- exchangeWrapper = new ExchangeWrapper(exchange, zeroEx);
-
- const defaultOrderParams = {
- ...constants.STATIC_ORDER_PARAMS,
- exchangeAddress: exchange.address,
- makerAddress,
- feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
- };
- const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
- orderFactory = new OrderFactory(privateKey, defaultOrderParams);
- });
-
- beforeEach(async () => {
- await blockchainLifecycle.startAsync();
- signedOrder = orderFactory.newSignedOrder();
- });
- afterEach(async () => {
- await blockchainLifecycle.revertAsync();
- });
-
- describe('getOrderHash', () => {
- it('should output the correct orderHash', async () => {
- const orderHashHex = await exchangeWrapper.getOrderHashAsync(signedOrder);
- expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
- });
- });
-
- describe('isValidSignature', () => {
- beforeEach(async () => {
- signedOrder = orderFactory.newSignedOrder();
- });
-
- it('should return true with a valid signature', async () => {
- const success = await exchangeWrapper.isValidSignatureAsync(signedOrder);
- expect(success).to.be.true();
- });
-
- it('should return false with an invalid signature', async () => {
- const invalidR = ethUtil.sha3('invalidR');
- const invalidS = ethUtil.sha3('invalidS');
- const invalidSigBuff = Buffer.concat([
- ethUtil.toBuffer(signedOrder.signature.slice(0, 6)),
- invalidR,
- invalidS,
- ]);
- const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`;
- signedOrder.signature = invalidSigHex;
- const success = await exchangeWrapper.isValidSignatureAsync(signedOrder);
- expect(success).to.be.false();
- });
- });
-
- describe('isRoundingError', () => {
- it('should return false if there is a rounding error of 0.1%', async () => {
- const numerator = new BigNumber(20);
- const denominator = new BigNumber(999);
- const target = new BigNumber(50);
- // rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1%
- const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
- expect(isRoundingError).to.be.false();
- });
-
- it('should return false if there is a rounding of 0.09%', async () => {
- const numerator = new BigNumber(20);
- const denominator = new BigNumber(9991);
- const target = new BigNumber(500);
- // rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09%
- const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
- expect(isRoundingError).to.be.false();
- });
-
- it('should return true if there is a rounding error of 0.11%', async () => {
- const numerator = new BigNumber(20);
- const denominator = new BigNumber(9989);
- const target = new BigNumber(500);
- // rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011%
- const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
- expect(isRoundingError).to.be.true();
- });
-
- it('should return true if there is a rounding error > 0.1%', async () => {
- const numerator = new BigNumber(3);
- const denominator = new BigNumber(7);
- const target = new BigNumber(10);
- // rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67%
- const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
- expect(isRoundingError).to.be.true();
- });
-
- it('should return false when there is no rounding error', async () => {
- const numerator = new BigNumber(1);
- const denominator = new BigNumber(2);
- const target = new BigNumber(10);
-
- const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
- expect(isRoundingError).to.be.false();
- });
-
- it('should return false when there is rounding error <= 0.1%', async () => {
- // randomly generated numbers
- const numerator = new BigNumber(76564);
- const denominator = new BigNumber(676373677);
- const target = new BigNumber(105762562);
- // rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) /
- // (76564*105762562/676373677) = 0.0007%
- const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
- expect(isRoundingError).to.be.false();
- });
- });
-
- describe('getPartialAmount', () => {
- it('should return the numerator/denominator*target', async () => {
- const numerator = new BigNumber(1);
- const denominator = new BigNumber(2);
- const target = new BigNumber(10);
-
- const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
- const expectedPartialAmount = 5;
- expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
- });
-
- it('should round down', async () => {
- const numerator = new BigNumber(2);
- const denominator = new BigNumber(3);
- const target = new BigNumber(10);
-
- const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
- const expectedPartialAmount = 6;
- expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
- });
-
- it('should round .5 down', async () => {
- const numerator = new BigNumber(1);
- const denominator = new BigNumber(20);
- const target = new BigNumber(10);
-
- const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
- const expectedPartialAmount = 0;
- expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
- });
- });
-});
diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts
new file mode 100644
index 000000000..0074cdff7
--- /dev/null
+++ b/packages/contracts/test/exchange/libs.ts
@@ -0,0 +1,155 @@
+import { ZeroEx } from '0x.js';
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import ethUtil = require('ethereumjs-util');
+
+import { TestLibsContract } from '../../src/contract_wrappers/generated/test_libs';
+import { addressUtils } from '../../src/utils/address_utils';
+import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
+import { constants } from '../../src/utils/constants';
+import { OrderFactory } from '../../src/utils/order_factory';
+import { orderUtils } from '../../src/utils/order_utils';
+import { ContractName, SignedOrder } from '../../src/utils/types';
+import { chaiSetup } from '../utils/chai_setup';
+import { deployer } from '../utils/deployer';
+import { provider, web3Wrapper } from '../utils/web3_wrapper';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+describe('Exchange libs', () => {
+ let signedOrder: SignedOrder;
+ let orderFactory: OrderFactory;
+ let libs: TestLibsContract;
+
+ before(async () => {
+ const accounts = await web3Wrapper.getAvailableAddressesAsync();
+ const makerAddress = accounts[0];
+ const libsInstance = await deployer.deployAsync(ContractName.TestLibs);
+ libs = new TestLibsContract(libsInstance.abi, libsInstance.address, provider);
+ const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID });
+
+ const defaultOrderParams = {
+ ...constants.STATIC_ORDER_PARAMS,
+ exchangeAddress: libs.address,
+ makerAddress,
+ feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
+ makerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
+ takerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
+ };
+ const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
+ orderFactory = new OrderFactory(privateKey, defaultOrderParams);
+ });
+
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ signedOrder = orderFactory.newSignedOrder();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+
+ describe('LibOrder', () => {
+ describe('getOrderHash', () => {
+ it('should output the correct orderHash', async () => {
+ const orderHashHex = await libs.publicGetOrderHash.callAsync(signedOrder);
+ expect(orderUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
+ });
+ });
+ });
+
+ describe('LibMath', () => {
+ describe('isRoundingError', () => {
+ it('should return false if there is a rounding error of 0.1%', async () => {
+ const numerator = new BigNumber(20);
+ const denominator = new BigNumber(999);
+ const target = new BigNumber(50);
+ // rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1%
+ const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target);
+ expect(isRoundingError).to.be.false();
+ });
+
+ it('should return false if there is a rounding of 0.09%', async () => {
+ const numerator = new BigNumber(20);
+ const denominator = new BigNumber(9991);
+ const target = new BigNumber(500);
+ // rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09%
+ const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target);
+ expect(isRoundingError).to.be.false();
+ });
+
+ it('should return true if there is a rounding error of 0.11%', async () => {
+ const numerator = new BigNumber(20);
+ const denominator = new BigNumber(9989);
+ const target = new BigNumber(500);
+ // rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011%
+ const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target);
+ expect(isRoundingError).to.be.true();
+ });
+
+ it('should return true if there is a rounding error > 0.1%', async () => {
+ const numerator = new BigNumber(3);
+ const denominator = new BigNumber(7);
+ const target = new BigNumber(10);
+ // rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67%
+ const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target);
+ expect(isRoundingError).to.be.true();
+ });
+
+ it('should return false when there is no rounding error', async () => {
+ const numerator = new BigNumber(1);
+ const denominator = new BigNumber(2);
+ const target = new BigNumber(10);
+
+ const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target);
+ expect(isRoundingError).to.be.false();
+ });
+
+ it('should return false when there is rounding error <= 0.1%', async () => {
+ // randomly generated numbers
+ const numerator = new BigNumber(76564);
+ const denominator = new BigNumber(676373677);
+ const target = new BigNumber(105762562);
+ // rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) /
+ // (76564*105762562/676373677) = 0.0007%
+ const isRoundingError = await libs.publicIsRoundingError.callAsync(numerator, denominator, target);
+ expect(isRoundingError).to.be.false();
+ });
+ });
+
+ describe('getPartialAmount', () => {
+ it('should return the numerator/denominator*target', async () => {
+ const numerator = new BigNumber(1);
+ const denominator = new BigNumber(2);
+ const target = new BigNumber(10);
+
+ const partialAmount = await libs.publicGetPartialAmount.callAsync(numerator, denominator, target);
+ const expectedPartialAmount = 5;
+ expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
+ });
+
+ it('should round down', async () => {
+ const numerator = new BigNumber(2);
+ const denominator = new BigNumber(3);
+ const target = new BigNumber(10);
+
+ const partialAmount = await libs.publicGetPartialAmount.callAsync(numerator, denominator, target);
+ const expectedPartialAmount = 6;
+ expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
+ });
+
+ it('should round .5 down', async () => {
+ const numerator = new BigNumber(1);
+ const denominator = new BigNumber(20);
+ const target = new BigNumber(10);
+
+ const partialAmount = await libs.publicGetPartialAmount.callAsync(numerator, denominator, target);
+ const expectedPartialAmount = 0;
+ expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
+ });
+ });
+ });
+});
diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts
new file mode 100644
index 000000000..f47999bfa
--- /dev/null
+++ b/packages/contracts/test/exchange/signature_validator.ts
@@ -0,0 +1,93 @@
+import { ZeroEx } from '0x.js';
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import ethUtil = require('ethereumjs-util');
+
+import { TestSignatureValidatorContract } from '../../src/contract_wrappers/generated/test_signature_validator';
+import { addressUtils } from '../../src/utils/address_utils';
+import { assetProxyUtils } from '../../src/utils/asset_proxy_utils';
+import { constants } from '../../src/utils/constants';
+import { OrderFactory } from '../../src/utils/order_factory';
+import { orderUtils } from '../../src/utils/order_utils';
+import { ContractName, SignedOrder } from '../../src/utils/types';
+import { chaiSetup } from '../utils/chai_setup';
+import { deployer } from '../utils/deployer';
+import { provider, web3Wrapper } from '../utils/web3_wrapper';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+describe('MixinSignatureValidator', () => {
+ let signedOrder: SignedOrder;
+ let orderFactory: OrderFactory;
+ let signatureValidator: TestSignatureValidatorContract;
+
+ before(async () => {
+ const accounts = await web3Wrapper.getAvailableAddressesAsync();
+ const makerAddress = accounts[0];
+ const signatureValidatorInstance = await deployer.deployAsync(ContractName.TestSignatureValidator);
+ signatureValidator = new TestSignatureValidatorContract(
+ signatureValidatorInstance.abi,
+ signatureValidatorInstance.address,
+ provider,
+ );
+ const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID });
+
+ const defaultOrderParams = {
+ ...constants.STATIC_ORDER_PARAMS,
+ exchangeAddress: signatureValidatorInstance.address,
+ makerAddress,
+ feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
+ makerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
+ takerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
+ };
+ const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
+ orderFactory = new OrderFactory(privateKey, defaultOrderParams);
+ });
+
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ signedOrder = orderFactory.newSignedOrder();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+
+ describe('isValidSignature', () => {
+ beforeEach(async () => {
+ signedOrder = orderFactory.newSignedOrder();
+ });
+
+ it('should return true with a valid signature', async () => {
+ const orderHashHex = orderUtils.getOrderHashHex(signedOrder);
+ const success = await signatureValidator.publicIsValidSignature.callAsync(
+ orderHashHex,
+ signedOrder.makerAddress,
+ signedOrder.signature,
+ );
+ expect(success).to.be.true();
+ });
+
+ it('should return false with an invalid signature', async () => {
+ const invalidR = ethUtil.sha3('invalidR');
+ const invalidS = ethUtil.sha3('invalidS');
+ const invalidSigBuff = Buffer.concat([
+ ethUtil.toBuffer(signedOrder.signature.slice(0, 6)),
+ invalidR,
+ invalidS,
+ ]);
+ const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`;
+ signedOrder.signature = invalidSigHex;
+ const orderHashHex = orderUtils.getOrderHashHex(signedOrder);
+ const success = await signatureValidator.publicIsValidSignature.callAsync(
+ orderHashHex,
+ signedOrder.makerAddress,
+ signedOrder.signature,
+ );
+ expect(success).to.be.false();
+ });
+ });
+});