aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/contracts/package.json7
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol2
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol11
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/ISigner.sol5
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol46
-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.sol7
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol38
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol14
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol12
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol29
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol3
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol16
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol4
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol3
-rw-r--r--packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol2
-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/contracts/current/tokens/ERC721Token/ERC721Token.sol406
-rw-r--r--packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol60
-rw-r--r--packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol105
-rw-r--r--packages/contracts/src/contracts/previous/TokenRegistry/ITokenRegistery.sol (renamed from packages/contracts/src/contracts/current/protocol/TokenRegistry/ITokenRegistery.sol)2
-rw-r--r--packages/contracts/src/contracts/previous/TokenRegistry/TokenRegistry.sol (renamed from packages/contracts/src/contracts/current/protocol/TokenRegistry/TokenRegistry.sol)2
-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
29 files changed, 1099 insertions, 323 deletions
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index a85e9aa4f..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",
@@ -76,7 +76,6 @@
"ethereumjs-util": "^5.1.1",
"ethers-contracts": "^2.2.1",
"lodash": "^4.17.4",
- "web3": "^0.20.0",
- "zeppelin-solidity": "^1.8.0"
+ "web3": "^0.20.0"
}
}
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol
index 466d0b871..eeb7e6710 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/proxies/ERC721Proxy.sol
@@ -21,7 +21,7 @@ pragma solidity ^0.4.21;
import "../IAssetProxy.sol";
import "../../../utils/LibBytes/LibBytes.sol";
import "../../../utils/Authorizable/Authorizable.sol";
-import "zeppelin-solidity/contracts/token/ERC721/ERC721Token.sol";
+import "../../../tokens/ERC721Token/ERC721Token.sol";
contract ERC721Proxy is
LibBytes,
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
index caf48bfca..e78446b99 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
@@ -27,17 +27,16 @@ import "./MixinAssetProxyDispatcher.sol";
import "./MixinTransactions.sol";
contract Exchange is
+ MixinWrapperFunctions,
MixinExchangeCore,
- MixinSignatureValidator,
MixinSettlement,
- MixinWrapperFunctions,
- MixinAssetProxyDispatcher,
- MixinTransactions
+ MixinSignatureValidator,
+ MixinTransactions,
+ MixinAssetProxyDispatcher
{
string constant public VERSION = "2.0.1-alpha";
- function Exchange(
- bytes memory _zrxProxyData)
+ function Exchange(bytes memory _zrxProxyData)
public
MixinExchangeCore()
MixinSignatureValidator()
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/LibFillResults.sol b/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol
new file mode 100644
index 000000000..41096f448
--- /dev/null
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/LibFillResults.sol
@@ -0,0 +1,46 @@
+/*
+
+ 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 LibFillResults is SafeMath {
+
+ struct FillResults {
+ uint256 makerAssetFilledAmount;
+ uint256 takerAssetFilledAmount;
+ uint256 makerFeePaid;
+ uint256 takerFeePaid;
+ }
+
+ /// @dev Adds properties of both FillResults instances.
+ /// Modifies the first FillResults instance specified.
+ /// @param totalFillResults Fill results instance that will be added onto.
+ /// @param singleFillResults Fill results instance that will be added to totalFillResults.
+ function addFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults)
+ internal
+ pure
+ {
+ totalFillResults.makerAssetFilledAmount = safeAdd(totalFillResults.makerAssetFilledAmount, singleFillResults.makerAssetFilledAmount);
+ totalFillResults.takerAssetFilledAmount = safeAdd(totalFillResults.takerAssetFilledAmount, singleFillResults.takerAssetFilledAmount);
+ totalFillResults.makerFeePaid = safeAdd(totalFillResults.makerFeePaid, singleFillResults.makerFeePaid);
+ totalFillResults.takerFeePaid = safeAdd(totalFillResults.takerFeePaid, singleFillResults.takerFeePaid);
+ }
+} \ No newline at end of file
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 eab8e04a1..b03bf464a 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
@@ -18,9 +18,9 @@
pragma solidity ^0.4.21;
-import "./mixins/MAssetProxyDispatcher.sol";
-import "../AssetProxy/IAssetProxy.sol";
import "../../utils/Ownable/Ownable.sol";
+import "../AssetProxy/IAssetProxy.sol";
+import "./mixins/MAssetProxyDispatcher.sol";
contract MixinAssetProxyDispatcher is
Ownable,
@@ -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 80120bc74..4ca271b2a 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol
@@ -19,27 +19,27 @@
pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
+import "./LibFillResults.sol";
+import "./LibOrder.sol";
+import "./LibErrors.sol";
+import "./LibMath.sol";
import "./mixins/MExchangeCore.sol";
import "./mixins/MSettlement.sol";
import "./mixins/MSignatureValidator.sol";
import "./mixins/MTransactions.sol";
-import "./LibOrder.sol";
-import "./LibErrors.sol";
-import "./LibPartialAmount.sol";
-import "../../utils/SafeMath/SafeMath.sol";
/// @dev Provides MExchangeCore
/// @dev Consumes MSettlement
/// @dev Consumes MSignatureValidator
contract MixinExchangeCore is
LibOrder,
+ LibFillResults,
+ LibErrors,
+ LibMath,
MExchangeCore,
MSettlement,
MSignatureValidator,
- MTransactions,
- SafeMath,
- LibErrors,
- LibPartialAmount
+ MTransactions
{
// Mapping of orderHash => amount of takerAsset already bought by maker
mapping (bytes32 => uint256) public filled;
@@ -217,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 ae41c7a86..cab2ccfb6 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
@@ -21,19 +21,21 @@ pragma experimental ABIEncoderV2;
import "./mixins/MSettlement.sol";
import "./mixins/MAssetProxyDispatcher.sol";
-import "./LibPartialAmount.sol";
+import "./LibOrder.sol";
+import "./LibMath.sol";
import "../AssetProxy/IAssetProxy.sol";
/// @dev Provides MixinSettlement
contract MixinSettlement is
+ LibMath,
MSettlement,
- MAssetProxyDispatcher,
- LibPartialAmount
+ MAssetProxyDispatcher
{
- bytes ZRX_PROXY_DATA;
+ bytes internal ZRX_PROXY_DATA;
function zrxProxyData()
- external view
+ external
+ view
returns (bytes memory)
{
return ZRX_PROXY_DATA;
@@ -46,7 +48,7 @@ contract MixinSettlement is
}
function settleOrder(
- Order memory order,
+ LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFilledAmount)
internal
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
index 48e7be424..690a70820 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol
@@ -23,9 +23,8 @@ import "./mixins/MSignatureValidator.sol";
import "./ISigner.sol";
/// @dev Provides MSignatureValidator
-contract MixinSignatureValidator is
- MSignatureValidator
-{
+contract MixinSignatureValidator is MSignatureValidator {
+
enum SignatureType {
Illegal, // Default value
Invalid,
@@ -49,7 +48,8 @@ contract MixinSignatureValidator is
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.)
@@ -166,8 +166,8 @@ contract MixinSignatureValidator is
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 4d6ba17dd..105c0f0a0 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
@@ -19,17 +19,19 @@
pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
-import "./mixins/MExchangeCore.sol";
-import "./LibPartialAmount.sol";
-import "../../utils/SafeMath/SafeMath.sol";
import "../../utils/LibBytes/LibBytes.sol";
+import "./mixins/MExchangeCore.sol";
+import "./LibMath.sol";
+import "./LibOrder.sol";
+import "./LibFillResults.sol";
/// @dev Consumes MExchangeCore
contract MixinWrapperFunctions is
- MExchangeCore,
- SafeMath,
+ LibOrder,
+ LibFillResults,
+ LibMath,
LibBytes,
- LibPartialAmount
+ MExchangeCore
{
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
/// @param order Order struct containing order specifications.
@@ -489,19 +491,4 @@ contract MixinWrapperFunctions is
cancelOrder(orders[i]);
}
}
-
- /// @dev Adds properties of both FillResults instances.
- /// Modifies the first FillResults instance specified.
- /// @param totalFillResults Fill results instance that will be added onto.
- /// @param singleFillResults Fill results instance that will be added to totalFillResults.
- function addFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults)
- internal
- pure
- {
- totalFillResults.makerAssetFilledAmount = safeAdd(totalFillResults.makerAssetFilledAmount, singleFillResults.makerAssetFilledAmount);
- totalFillResults.takerAssetFilledAmount = safeAdd(totalFillResults.takerAssetFilledAmount, singleFillResults.takerAssetFilledAmount);
- totalFillResults.makerFeePaid = safeAdd(totalFillResults.makerFeePaid, singleFillResults.makerFeePaid);
- totalFillResults.takerFeePaid = safeAdd(totalFillResults.takerFeePaid, singleFillResults.takerFeePaid);
- }
-
}
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/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol
index 9a7f80109..656df079e 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol
@@ -20,24 +20,18 @@ pragma solidity ^0.4.21;
pragma experimental ABIEncoderV2;
import "../LibOrder.sol";
+import "../LibFillResults.sol";
-contract MExchangeCore is LibOrder {
-
- struct FillResults {
- uint256 makerAssetFilledAmount;
- uint256 takerAssetFilledAmount;
- uint256 makerFeePaid;
- uint256 takerFeePaid;
- }
+contract MExchangeCore {
function fillOrder(
- Order memory order,
+ LibOrder.Order memory order,
uint256 takerAssetFillAmount,
bytes memory signature)
public
- returns (FillResults memory fillResults);
+ returns (LibFillResults.FillResults memory fillResults);
- function cancelOrder(Order memory order)
+ function cancelOrder(LibOrder.Order memory order)
public
returns (bool);
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol
index 172138f2d..0d7e59a9a 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSettlement.sol
@@ -21,10 +21,10 @@ pragma experimental ABIEncoderV2;
import "../LibOrder.sol";
-contract MSettlement is LibOrder {
+contract MSettlement {
function settleOrder(
- Order memory order,
+ LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFilledAmount)
internal
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/DummyERC721Token/DummyERC721Token.sol b/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
index 7a635f15f..4fbaa6b74 100644
--- a/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
+++ b/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
@@ -17,7 +17,7 @@
*/
pragma solidity ^0.4.21;
-import "zeppelin-solidity/contracts/token/ERC721/ERC721Token.sol";
+import "../../tokens/ERC721Token/ERC721Token.sol";
import "../../utils/Ownable/Ownable.sol";
contract DummyERC721Token is
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/contracts/current/tokens/ERC721Token/ERC721Token.sol b/packages/contracts/src/contracts/current/tokens/ERC721Token/ERC721Token.sol
new file mode 100644
index 000000000..3bf064c3f
--- /dev/null
+++ b/packages/contracts/src/contracts/current/tokens/ERC721Token/ERC721Token.sol
@@ -0,0 +1,406 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 Smart Contract Solutions, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+pragma solidity ^0.4.21;
+
+import "./IERC721Token.sol";
+import "./IERC721Receiver.sol";
+import "../../utils/SafeMath/SafeMath.sol";
+
+/**
+ * @title ERC721 Non-Fungible Token Standard basic implementation
+ * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+ * Modified from https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC721/ERC721BasicToken.sol
+ */
+contract ERC721Token is
+ IERC721Token,
+ SafeMath
+{
+ // Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
+ // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
+ bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;
+
+ // Mapping from token ID to owner
+ mapping (uint256 => address) internal tokenOwner;
+
+ // Mapping from token ID to approved address
+ mapping (uint256 => address) internal tokenApprovals;
+
+ // Mapping from owner to number of owned token
+ mapping (address => uint256) internal ownedTokensCount;
+
+ // Mapping from owner to operator approvals
+ mapping (address => mapping (address => bool)) internal operatorApprovals;
+
+ /**
+ * @dev Guarantees msg.sender is owner of the given token
+ * @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender
+ */
+ modifier onlyOwnerOf(uint256 _tokenId) {
+ require(ownerOf(_tokenId) == msg.sender);
+ _;
+ }
+
+ /**
+ * @dev Checks msg.sender can transfer a token, by being owner, approved, or operator
+ * @param _tokenId uint256 ID of the token to validate
+ */
+ modifier canTransfer(uint256 _tokenId) {
+ require(isApprovedOrOwner(msg.sender, _tokenId));
+ _;
+ }
+
+ function ERC721Token(
+ string _name,
+ string _symbol)
+ public
+ {
+ name_ = _name;
+ symbol_ = _symbol;
+ }
+
+ /**
+ * @dev Gets the token name
+ * @return string representing the token name
+ */
+ function name()
+ public
+ view
+ returns (string)
+ {
+ return name_;
+ }
+
+ /**
+ * @dev Gets the token symbol
+ * @return string representing the token symbol
+ */
+ function symbol()
+ public
+ view
+ returns (string)
+ {
+ return symbol_;
+ }
+
+ /**
+ * @dev Gets the balance of the specified address
+ * @param _owner address to query the balance of
+ * @return uint256 representing the amount owned by the passed address
+ */
+ function balanceOf(address _owner)
+ public
+ view
+ returns (uint256)
+ {
+ require(_owner != address(0));
+ return ownedTokensCount[_owner];
+ }
+
+ /**
+ * @dev Gets the owner of the specified token ID
+ * @param _tokenId uint256 ID of the token to query the owner of
+ * @return owner address currently marked as the owner of the given token ID
+ */
+ function ownerOf(uint256 _tokenId)
+ public
+ view
+ returns (address)
+ {
+ address owner = tokenOwner[_tokenId];
+ require(owner != address(0));
+ return owner;
+ }
+
+ /**
+ * @dev Returns whether the specified token exists
+ * @param _tokenId uint256 ID of the token to query the existance of
+ * @return whether the token exists
+ */
+ function exists(uint256 _tokenId)
+ public
+ view
+ returns (bool)
+ {
+ address owner = tokenOwner[_tokenId];
+ return owner != address(0);
+ }
+
+ /**
+ * @dev Approves another address to transfer the given token ID
+ * @dev The zero address indicates there is no approved address.
+ * @dev There can only be one approved address per token at a given time.
+ * @dev Can only be called by the token owner or an approved operator.
+ * @param _to address to be approved for the given token ID
+ * @param _tokenId uint256 ID of the token to be approved
+ */
+ function approve(address _to, uint256 _tokenId)
+ public
+ {
+ address owner = ownerOf(_tokenId);
+ require(_to != owner);
+ require(msg.sender == owner || isApprovedForAll(owner, msg.sender));
+
+ if (getApproved(_tokenId) != address(0) || _to != address(0)) {
+ tokenApprovals[_tokenId] = _to;
+ emit Approval(owner, _to, _tokenId);
+ }
+ }
+
+ /**
+ * @dev Gets the approved address for a token ID, or zero if no address set
+ * @param _tokenId uint256 ID of the token to query the approval of
+ * @return address currently approved for a the given token ID
+ */
+ function getApproved(uint256 _tokenId)
+ public
+ view
+ returns (address)
+ {
+ return tokenApprovals[_tokenId];
+ }
+
+ /**
+ * @dev Sets or unsets the approval of a given operator
+ * @dev An operator is allowed to transfer all tokens of the sender on their behalf
+ * @param _to operator address to set the approval
+ * @param _approved representing the status of the approval to be set
+ */
+ function setApprovalForAll(address _to, bool _approved)
+ public
+ {
+ require(_to != msg.sender);
+ operatorApprovals[msg.sender][_to] = _approved;
+ emit ApprovalForAll(msg.sender, _to, _approved);
+ }
+
+ /**
+ * @dev Tells whether an operator is approved by a given owner
+ * @param _owner owner address which you want to query the approval of
+ * @param _operator operator address which you want to query the approval of
+ * @return bool whether the given operator is approved by the given owner
+ */
+ function isApprovedForAll(address _owner, address _operator)
+ public
+ view
+ returns (bool)
+ {
+ return operatorApprovals[_owner][_operator];
+ }
+
+ /**
+ * @dev Transfers the ownership of a given token ID to another address
+ * @dev Usage of this method is discouraged, use `safeTransferFrom` whenever possible
+ * @dev Requires the msg sender to be the owner, approved, or operator
+ * @param _from current owner of the token
+ * @param _to address to receive the ownership of the given token ID
+ * @param _tokenId uint256 ID of the token to be transferred
+ */
+ function transferFrom(address _from, address _to, uint256 _tokenId)
+ public
+ canTransfer(_tokenId)
+ {
+ require(_from != address(0));
+ require(_to != address(0));
+
+ clearApproval(_from, _tokenId);
+ removeTokenFrom(_from, _tokenId);
+ addTokenTo(_to, _tokenId);
+
+ emit Transfer(_from, _to, _tokenId);
+ }
+
+ /**
+ * @dev Safely transfers the ownership of a given token ID to another address
+ * @dev If the target address is a contract, it must implement `onERC721Received`,
+ * which is called upon a safe transfer, and return the magic value
+ * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
+ * the transfer is reverted.
+ * @dev Requires the msg sender to be the owner, approved, or operator
+ * @param _from current owner of the token
+ * @param _to address to receive the ownership of the given token ID
+ * @param _tokenId uint256 ID of the token to be transferred
+ */
+ function safeTransferFrom(
+ address _from,
+ address _to,
+ uint256 _tokenId)
+ public
+ canTransfer(_tokenId)
+ {
+ // solium-disable-next-line arg-overflow
+ safeTransferFrom(_from, _to, _tokenId, "");
+ }
+
+ /**
+ * @dev Safely transfers the ownership of a given token ID to another address
+ * @dev If the target address is a contract, it must implement `onERC721Received`,
+ * which is called upon a safe transfer, and return the magic value
+ * `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise,
+ * the transfer is reverted.
+ * @dev Requires the msg sender to be the owner, approved, or operator
+ * @param _from current owner of the token
+ * @param _to address to receive the ownership of the given token ID
+ * @param _tokenId uint256 ID of the token to be transferred
+ * @param _data bytes data to send along with a safe transfer check
+ */
+ function safeTransferFrom(
+ address _from,
+ address _to,
+ uint256 _tokenId,
+ bytes _data)
+ public
+ canTransfer(_tokenId)
+ {
+ transferFrom(_from, _to, _tokenId);
+ // solium-disable-next-line arg-overflow
+ require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
+ }
+
+ /**
+ * @dev Returns whether the given spender can transfer a given token ID
+ * @param _spender address of the spender to query
+ * @param _tokenId uint256 ID of the token to be transferred
+ * @return bool whether the msg.sender is approved for the given token ID,
+ * is an operator of the owner, or is the owner of the token
+ */
+ function isApprovedOrOwner(address _spender, uint256 _tokenId)
+ internal
+ view
+ returns (bool)
+ {
+ address owner = ownerOf(_tokenId);
+ return _spender == owner || getApproved(_tokenId) == _spender || isApprovedForAll(owner, _spender);
+ }
+
+ /**
+ * @dev Internal function to mint a new token
+ * @dev Reverts if the given token ID already exists
+ * @param _to The address that will own the minted token
+ * @param _tokenId uint256 ID of the token to be minted by the msg.sender
+ */
+ function _mint(address _to, uint256 _tokenId)
+ internal
+ {
+ require(_to != address(0));
+ addTokenTo(_to, _tokenId);
+ emit Transfer(address(0), _to, _tokenId);
+ }
+
+ /**
+ * @dev Internal function to burn a specific token
+ * @dev Reverts if the token does not exist
+ * @param _tokenId uint256 ID of the token being burned by the msg.sender
+ */
+ function _burn(address _owner, uint256 _tokenId)
+ internal
+ {
+ clearApproval(_owner, _tokenId);
+ removeTokenFrom(_owner, _tokenId);
+ emit Transfer(_owner, address(0), _tokenId);
+ }
+
+ /**
+ * @dev Internal function to clear current approval of a given token ID
+ * @dev Reverts if the given address is not indeed the owner of the token
+ * @param _owner owner of the token
+ * @param _tokenId uint256 ID of the token to be transferred
+ */
+ function clearApproval(address _owner, uint256 _tokenId)
+ internal
+ {
+ require(ownerOf(_tokenId) == _owner);
+ if (tokenApprovals[_tokenId] != address(0)) {
+ tokenApprovals[_tokenId] = address(0);
+ emit Approval(_owner, address(0), _tokenId);
+ }
+ }
+
+ /**
+ * @dev Internal function to add a token ID to the list of a given address
+ * @param _to address representing the new owner of the given token ID
+ * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
+ */
+ function addTokenTo(address _to, uint256 _tokenId)
+ internal
+ {
+ require(tokenOwner[_tokenId] == address(0));
+ tokenOwner[_tokenId] = _to;
+ ownedTokensCount[_to] = safeAdd(ownedTokensCount[_to], 1);
+ }
+
+ /**
+ * @dev Internal function to remove a token ID from the list of a given address
+ * @param _from address representing the previous owner of the given token ID
+ * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
+ */
+ function removeTokenFrom(address _from, uint256 _tokenId)
+ internal
+ {
+ require(ownerOf(_tokenId) == _from);
+ ownedTokensCount[_from] = safeSub(ownedTokensCount[_from], 1);
+ tokenOwner[_tokenId] = address(0);
+ }
+
+ /**
+ * @dev Internal function to invoke `onERC721Received` on a target address
+ * @dev The call is not executed if the target address is not a contract
+ * @param _from address representing the previous owner of the given token ID
+ * @param _to target address that will receive the tokens
+ * @param _tokenId uint256 ID of the token to be transferred
+ * @param _data bytes optional data to send along with the call
+ * @return whether the call correctly returned the expected magic value
+ */
+ function checkAndCallSafeTransfer(
+ address _from,
+ address _to,
+ uint256 _tokenId,
+ bytes _data)
+ internal
+ returns (bool)
+ {
+ if (!isContract(_to)) {
+ return true;
+ }
+ bytes4 retval = IERC721Receiver(_to).onERC721Received(_from, _tokenId, _data);
+ return (retval == ERC721_RECEIVED);
+ }
+
+ function isContract(address addr)
+ internal
+ view
+ returns (bool)
+ {
+ uint256 size;
+ // XXX Currently there is no better way to check if there is a contract in an address
+ // than to check the size of the code at that address.
+ // See https://ethereum.stackexchange.com/a/14016/36603
+ // for more details about how this works.
+ // TODO Check this again before the Serenity release, because all addresses will be
+ // contracts then.
+ assembly { size := extcodesize(addr) } // solium-disable-line security/no-inline-assembly
+ return size > 0;
+ }
+} \ No newline at end of file
diff --git a/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol b/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol
new file mode 100644
index 000000000..26871cc89
--- /dev/null
+++ b/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Receiver.sol
@@ -0,0 +1,60 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 Smart Contract Solutions, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+pragma solidity ^0.4.21;
+
+/**
+ * @title ERC721 token receiver interface
+ * @dev Interface for any contract that wants to support safeTransfers
+ * rom ERC721 asset contracts.
+ * Modified from https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC721/ERC721Receiver.sol
+ */
+contract IERC721Receiver {
+ /**
+ * @dev Magic value to be returned upon successful reception of an NFT
+ * Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`,
+ * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
+ */
+ bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;
+
+ /**
+ * @notice Handle the receipt of an NFT
+ * @dev The ERC721 smart contract calls this function on the recipient
+ * after a `safetransfer`. This function MAY throw to revert and reject the
+ * transfer. This function MUST use 50,000 gas or less. Return of other
+ * than the magic value MUST result in the transaction being reverted.
+ * Note: the contract address is always the message sender.
+ * @param _from The sending address
+ * @param _tokenId The NFT identifier which is being transfered
+ * @param _data Additional data with no specified format
+ * @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
+ */
+ function onERC721Received(
+ address _from,
+ uint256 _tokenId,
+ bytes _data)
+ public
+ returns (bytes4);
+} \ No newline at end of file
diff --git a/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol b/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol
new file mode 100644
index 000000000..73741ed53
--- /dev/null
+++ b/packages/contracts/src/contracts/current/tokens/ERC721Token/IERC721Token.sol
@@ -0,0 +1,105 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 Smart Contract Solutions, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+pragma solidity ^0.4.21;
+
+/**
+ * @title ERC721 Non-Fungible Token Standard basic interface
+ * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
+ * Modified from https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC721/ERC721Basic.sol
+ */
+contract IERC721Token {
+ string internal name_;
+ string internal symbol_;
+
+ event Transfer(
+ address indexed _from,
+ address indexed _to,
+ uint256 _tokenId
+ );
+ event Approval(
+ address indexed _owner,
+ address indexed _approved,
+ uint256 _tokenId
+ );
+ event ApprovalForAll(
+ address indexed _owner,
+ address indexed _operator,
+ bool _approved
+ );
+
+ function name()
+ public
+ view
+ returns (string);
+ function symbol()
+ public
+ view
+ returns (string);
+
+ function balanceOf(address _owner)
+ public
+ view
+ returns (uint256 _balance);
+ function ownerOf(uint256 _tokenId)
+ public
+ view
+ returns (address _owner);
+ function exists(uint256 _tokenId)
+ public
+ view
+ returns (bool _exists);
+
+ function approve(address _to, uint256 _tokenId)
+ public;
+ function getApproved(uint256 _tokenId)
+ public
+ view
+ returns (address _operator);
+
+ function setApprovalForAll(address _operator, bool _approved)
+ public;
+ function isApprovedForAll(address _owner, address _operator)
+ public
+ view
+ returns (bool);
+
+ function transferFrom(
+ address _from,
+ address _to,
+ uint256 _tokenId)
+ public;
+ function safeTransferFrom(
+ address _from,
+ address _to,
+ uint256 _tokenId)
+ public;
+ function safeTransferFrom(
+ address _from,
+ address _to,
+ uint256 _tokenId,
+ bytes _data)
+ public;
+} \ No newline at end of file
diff --git a/packages/contracts/src/contracts/current/protocol/TokenRegistry/ITokenRegistery.sol b/packages/contracts/src/contracts/previous/TokenRegistry/ITokenRegistery.sol
index c140a5f24..b8bdaf3b9 100644
--- a/packages/contracts/src/contracts/current/protocol/TokenRegistry/ITokenRegistery.sol
+++ b/packages/contracts/src/contracts/previous/TokenRegistry/ITokenRegistery.sol
@@ -18,7 +18,7 @@
pragma solidity ^0.4.21;
-import { IOwnable_v1 as IOwnable } from "../../../previous/Ownable/IOwnable_v1.sol";
+import { IOwnable_v1 as IOwnable } from "../Ownable/IOwnable_v1.sol";
/// @title Token Registry - Stores metadata associated with ERC20 tokens. See ERC22 https://github.com/ethereum/EIPs/issues/22
/// @author Amir Bandeali - <amir@0xProject.com>, Will Warren - <will@0xProject.com>
diff --git a/packages/contracts/src/contracts/current/protocol/TokenRegistry/TokenRegistry.sol b/packages/contracts/src/contracts/previous/TokenRegistry/TokenRegistry.sol
index ede7c8c93..7417a10a3 100644
--- a/packages/contracts/src/contracts/current/protocol/TokenRegistry/TokenRegistry.sol
+++ b/packages/contracts/src/contracts/previous/TokenRegistry/TokenRegistry.sol
@@ -18,7 +18,7 @@
pragma solidity ^0.4.11;
-import { Ownable_v1 as Ownable } from "../../../previous/Ownable/Ownable_v1.sol";
+import { Ownable_v1 as Ownable } from "../Ownable/Ownable_v1.sol";
/// @title Token Registry - Stores metadata associated with ERC20 tokens. See ERC22 https://github.com/ethereum/EIPs/issues/22
/// @author Amir Bandeali - <amir@0xProject.com>, Will Warren - <will@0xProject.com>
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();
+ });
+ });
+});