Merge pull request #546 from 0xProject/feature/contracts/solidity-0.4.23
Use Solidity 0.4.23
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
"compile:comment":
|
||||
"Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846",
|
||||
"compile":
|
||||
"node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --contracts-dir src/contracts --artifacts-dir ../migrations/src/artifacts",
|
||||
"node ../deployer/lib/src/cli.js compile --contracts ${npm_package_config_contracts} --should-optimize true --contracts-dir src/contracts --artifacts-dir ../migrations/src/artifacts",
|
||||
"clean": "shx rm -rf ./lib ./src/contract_wrappers/generated",
|
||||
"generate_contract_wrappers":
|
||||
"node ../abi-gen/lib/index.js --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
|
||||
@@ -30,9 +30,9 @@
|
||||
},
|
||||
"config": {
|
||||
"abis":
|
||||
"../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|LibBytes|Authorizable).json",
|
||||
"../migrations/src/artifacts/@(DummyERC20Token|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|TestAssetProxyDispatcher|TestLibs|TestSignatureValidator|ERC20Proxy|ERC721Proxy|DummyERC721Token|TestLibBytes|MixinAuthorizable).json",
|
||||
"contracts":
|
||||
"Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,LibBytes,Authorizable"
|
||||
"Exchange,DummyERC20Token,ZRXToken,WETH9,MultiSigWallet,MultiSigWalletWithTimeLock,MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,TokenRegistry,TestAssetProxyDispatcher,TestLibs,TestSignatureValidator,ERC20Proxy,ERC721Proxy,DummyERC721Token,TestLibBytes,MixinAuthorizable"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -16,21 +16,28 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
||||
import "../../../utils/LibBytes/LibBytes.sol";
|
||||
import "../../../tokens/ERC20Token/IERC20Token.sol";
|
||||
import "../MixinAssetProxy.sol";
|
||||
import "../../utils/LibBytes/LibBytes.sol";
|
||||
import "../../tokens/ERC20Token/IERC20Token.sol";
|
||||
import "./MixinAssetProxy.sol";
|
||||
import "./MixinAuthorizable.sol";
|
||||
|
||||
contract ERC20Proxy is
|
||||
LibBytes,
|
||||
MixinAssetProxy
|
||||
MixinAssetProxy,
|
||||
MixinAuthorizable
|
||||
{
|
||||
|
||||
// Id of this proxy.
|
||||
uint8 constant PROXY_ID = 1;
|
||||
|
||||
// Revert reasons
|
||||
string constant INVALID_METADATA_LENGTH = "Metadata must have a length of 21.";
|
||||
string constant TRANSFER_FAILED = "Transfer failed.";
|
||||
string constant PROXY_ID_MISMATCH = "Proxy id in metadata does not match this proxy id.";
|
||||
|
||||
/// @dev Internal version of `transferFrom`.
|
||||
/// @param assetMetadata Encoded byte array.
|
||||
/// @param from Address to transfer asset from.
|
||||
@@ -44,15 +51,24 @@ contract ERC20Proxy is
|
||||
internal
|
||||
{
|
||||
// Data must be intended for this proxy.
|
||||
require(uint8(assetMetadata[0]) == PROXY_ID);
|
||||
require(
|
||||
uint8(assetMetadata[0]) == PROXY_ID,
|
||||
PROXY_ID_MISMATCH
|
||||
);
|
||||
|
||||
// Decode metadata.
|
||||
require(assetMetadata.length == 21);
|
||||
require(
|
||||
assetMetadata.length == 21,
|
||||
INVALID_METADATA_LENGTH
|
||||
);
|
||||
address token = readAddress(assetMetadata, 1);
|
||||
|
||||
// Transfer tokens.
|
||||
bool success = IERC20Token(token).transferFrom(from, to, amount);
|
||||
require(success == true);
|
||||
require(
|
||||
success == true,
|
||||
TRANSFER_FAILED
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Gets the proxy id associated with the proxy address.
|
||||
@@ -16,20 +16,28 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../../utils/LibBytes/LibBytes.sol";
|
||||
import "../../../tokens/ERC721Token/ERC721Token.sol";
|
||||
import "../MixinAssetProxy.sol";
|
||||
import "../../utils/LibBytes/LibBytes.sol";
|
||||
import "../../tokens/ERC721Token/ERC721Token.sol";
|
||||
import "./MixinAssetProxy.sol";
|
||||
import "./MixinAuthorizable.sol";
|
||||
|
||||
contract ERC721Proxy is
|
||||
LibBytes,
|
||||
MixinAssetProxy
|
||||
MixinAssetProxy,
|
||||
MixinAuthorizable
|
||||
{
|
||||
|
||||
// Id of this proxy.
|
||||
uint8 constant PROXY_ID = 2;
|
||||
|
||||
// Revert reasons
|
||||
string constant INVALID_TRANSFER_AMOUNT = "Transfer amount must equal 1.";
|
||||
string constant INVALID_METADATA_LENGTH = "Metadata must have a length of 53.";
|
||||
string constant PROXY_ID_MISMATCH = "Proxy id in metadata does not match this proxy id.";
|
||||
|
||||
/// @dev Internal version of `transferFrom`.
|
||||
/// @param assetMetadata Encoded byte array.
|
||||
/// @param from Address to transfer asset from.
|
||||
@@ -43,13 +51,22 @@ contract ERC721Proxy is
|
||||
internal
|
||||
{
|
||||
// Data must be intended for this proxy.
|
||||
require(uint8(assetMetadata[0]) == PROXY_ID);
|
||||
require(
|
||||
uint8(assetMetadata[0]) == PROXY_ID,
|
||||
PROXY_ID_MISMATCH
|
||||
);
|
||||
|
||||
// There exists only 1 of each token.
|
||||
require(amount == 1);
|
||||
require(
|
||||
amount == 1,
|
||||
INVALID_TRANSFER_AMOUNT
|
||||
);
|
||||
|
||||
// Decode metadata.
|
||||
require(assetMetadata.length == 53);
|
||||
// Decode metadata
|
||||
require(
|
||||
assetMetadata.length == 53,
|
||||
INVALID_METADATA_LENGTH
|
||||
);
|
||||
address token = readAddress(assetMetadata, 1);
|
||||
uint256 tokenId = readUint256(assetMetadata, 21);
|
||||
|
||||
@@ -16,17 +16,15 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./mixins/MAssetProxy.sol";
|
||||
import "./IAssetProxy.sol";
|
||||
import "../../utils/Authorizable/Authorizable.sol";
|
||||
import "./mixins/MAuthorizable.sol";
|
||||
|
||||
contract MixinAssetProxy is
|
||||
IAssetProxy,
|
||||
MAssetProxy,
|
||||
Authorizable
|
||||
MAuthorizable,
|
||||
MAssetProxy
|
||||
{
|
||||
|
||||
/// @dev Transfers assets. Either succeeds or throws.
|
||||
|
||||
@@ -16,46 +16,47 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./IAuthorizable.sol";
|
||||
import "../Ownable/Ownable.sol";
|
||||
import "./mixins/MAuthorizable.sol";
|
||||
import "../../utils/Ownable/Ownable.sol";
|
||||
|
||||
contract Authorizable is
|
||||
contract MixinAuthorizable is
|
||||
Ownable,
|
||||
IAuthorizable
|
||||
MAuthorizable
|
||||
{
|
||||
|
||||
// Revert reasons
|
||||
string constant SENDER_NOT_AUTHORIZED = "Sender not authorized to call this method.";
|
||||
string constant TARGET_NOT_AUTHORIZED = "Target address must be authorized.";
|
||||
string constant TARGET_ALREADY_AUTHORIZED = "Target must not already be authorized.";
|
||||
string constant INDEX_OUT_OF_BOUNDS = "Specified array index is out of bounds.";
|
||||
string constant INDEX_ADDRESS_MISMATCH = "Address found at index does not match target address.";
|
||||
|
||||
/// @dev Only authorized addresses can invoke functions with this modifier.
|
||||
modifier onlyAuthorized {
|
||||
require(authorized[msg.sender]);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier targetAuthorized(address target) {
|
||||
require(authorized[target]);
|
||||
_;
|
||||
}
|
||||
|
||||
modifier targetNotAuthorized(address target) {
|
||||
require(!authorized[target]);
|
||||
require(
|
||||
authorized[msg.sender],
|
||||
SENDER_NOT_AUTHORIZED
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
mapping (address => bool) public authorized;
|
||||
address[] public authorities;
|
||||
|
||||
/*
|
||||
* Public functions
|
||||
*/
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target)
|
||||
public
|
||||
external
|
||||
onlyOwner
|
||||
targetNotAuthorized(target)
|
||||
{
|
||||
require(
|
||||
!authorized[target],
|
||||
TARGET_ALREADY_AUTHORIZED
|
||||
);
|
||||
|
||||
authorized[target] = true;
|
||||
authorities.push(target);
|
||||
emit AuthorizedAddressAdded(target, msg.sender);
|
||||
@@ -64,10 +65,14 @@ contract Authorizable is
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target)
|
||||
public
|
||||
external
|
||||
onlyOwner
|
||||
targetAuthorized(target)
|
||||
{
|
||||
require(
|
||||
authorized[target],
|
||||
TARGET_NOT_AUTHORIZED
|
||||
);
|
||||
|
||||
delete authorized[target];
|
||||
for (uint i = 0; i < authorities.length; i++) {
|
||||
if (authorities[i] == target) {
|
||||
@@ -83,24 +88,28 @@ contract Authorizable is
|
||||
/// @param target Address to remove authorization from.
|
||||
/// @param index Index of target in authorities array.
|
||||
function removeAuthorizedAddressAtIndex(address target, uint256 index)
|
||||
public
|
||||
external
|
||||
{
|
||||
require(index < authorities.length);
|
||||
require(authorities[index] == target);
|
||||
require(
|
||||
index < authorities.length,
|
||||
INDEX_OUT_OF_BOUNDS
|
||||
);
|
||||
require(
|
||||
authorities[index] == target,
|
||||
INDEX_ADDRESS_MISMATCH
|
||||
);
|
||||
|
||||
delete authorized[target];
|
||||
authorities[index] = authorities[authorities.length - 1];
|
||||
authorities.length -= 1;
|
||||
emit AuthorizedAddressRemoved(target, msg.sender);
|
||||
}
|
||||
|
||||
/*
|
||||
* Public constant functions
|
||||
*/
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses()
|
||||
public view
|
||||
external
|
||||
view
|
||||
returns (address[] memory)
|
||||
{
|
||||
return authorities;
|
||||
@@ -16,12 +16,14 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../utils/Authorizable/IAuthorizable.sol";
|
||||
import "./IAuthorizable.sol";
|
||||
|
||||
contract IAssetProxy is IAuthorizable {
|
||||
contract IAssetProxy is
|
||||
IAuthorizable
|
||||
{
|
||||
|
||||
/// @dev Transfers assets. Either succeeds or throws.
|
||||
/// @param assetMetadata Byte array encoded for the respective asset proxy.
|
||||
@@ -16,37 +16,35 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract IAuthorizable {
|
||||
import "../../../utils/Ownable/IOwnable.sol";
|
||||
|
||||
contract IAuthorizable is
|
||||
IOwnable
|
||||
{
|
||||
|
||||
/// @dev Gets all authorized addresses.
|
||||
/// @return Array of authorized addresses.
|
||||
function getAuthorizedAddresses()
|
||||
public view
|
||||
external
|
||||
view
|
||||
returns (address[]);
|
||||
|
||||
/// @dev Authorizes an address.
|
||||
/// @param target Address to authorize.
|
||||
function addAuthorizedAddress(address target)
|
||||
public;
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
function removeAuthorizedAddress(address target)
|
||||
public;
|
||||
external;
|
||||
|
||||
/// @dev Removes authorizion of an address.
|
||||
/// @param target Address to remove authorization from.
|
||||
/// @param index Index of target in authorities array.
|
||||
function removeAuthorizedAddressAtIndex(address target, uint256 index)
|
||||
public;
|
||||
|
||||
event AuthorizedAddressAdded(
|
||||
address indexed target,
|
||||
address indexed caller);
|
||||
|
||||
event AuthorizedAddressRemoved(
|
||||
address indexed target,
|
||||
address indexed caller);
|
||||
external;
|
||||
}
|
||||
@@ -16,10 +16,14 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract MAssetProxy {
|
||||
import "../interfaces/IAssetProxy.sol";
|
||||
|
||||
contract MAssetProxy is
|
||||
IAssetProxy
|
||||
{
|
||||
|
||||
/// @dev Internal version of `transferFrom`.
|
||||
/// @param assetMetadata Encoded byte array.
|
||||
|
||||
@@ -16,20 +16,27 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract LibErrors {
|
||||
import "../interfaces/IAuthorizable.sol";
|
||||
|
||||
// Error Codes
|
||||
enum Errors {
|
||||
ORDER_EXPIRED, // Order has already expired
|
||||
ORDER_FULLY_FILLED, // Order has already been fully filled
|
||||
ORDER_CANCELLED, // Order has already been cancelled
|
||||
ROUNDING_ERROR_TOO_LARGE, // Rounding error too large
|
||||
INSUFFICIENT_BALANCE_OR_ALLOWANCE // Insufficient balance or allowance for token transfer
|
||||
}
|
||||
contract MAuthorizable is
|
||||
IAuthorizable
|
||||
{
|
||||
|
||||
event ExchangeError(uint8 indexed errorId, bytes32 indexed orderHash);
|
||||
// Event logged when a new address is authorized.
|
||||
event AuthorizedAddressAdded(
|
||||
address indexed target,
|
||||
address indexed caller
|
||||
);
|
||||
|
||||
// Event logged when a currently authorized address is unauthorized.
|
||||
event AuthorizedAddressRemoved(
|
||||
address indexed target,
|
||||
address indexed caller
|
||||
);
|
||||
|
||||
/// @dev Only authorized addresses can invoke functions with this modifier.
|
||||
modifier onlyAuthorized { _; }
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./MixinExchangeCore.sol";
|
||||
@@ -36,7 +36,7 @@ contract Exchange is
|
||||
{
|
||||
string constant public VERSION = "2.0.1-alpha";
|
||||
|
||||
function Exchange(bytes memory _zrxProxyData)
|
||||
constructor (bytes memory _zrxProxyData)
|
||||
public
|
||||
MixinExchangeCore()
|
||||
MixinSignatureValidator()
|
||||
|
||||
@@ -1,289 +0,0 @@
|
||||
/*
|
||||
|
||||
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;
|
||||
|
||||
contract IExchange {
|
||||
|
||||
// Error Codes
|
||||
enum Errors {
|
||||
ORDER_EXPIRED, // Order has already expired
|
||||
ORDER_FULLY_FILLED_OR_CANCELLED, // Order has already been fully filled or cancelled
|
||||
ROUNDING_ERROR_TOO_LARGE, // Rounding error too large
|
||||
INSUFFICIENT_BALANCE_OR_ALLOWANCE // Insufficient balance or allowance for token transfer
|
||||
}
|
||||
|
||||
event LogError(uint8 indexed errorId, bytes32 indexed orderHash);
|
||||
|
||||
event LogFill(
|
||||
address indexed maker,
|
||||
address taker,
|
||||
address indexed feeRecipient,
|
||||
bytes makerAssetData,
|
||||
bytes takerAssetData,
|
||||
uint256 makerAssetFilledAmount,
|
||||
uint256 takerAssetFilledAmount,
|
||||
uint256 makerFeePaid,
|
||||
uint256 takerFeePaid,
|
||||
bytes32 indexed orderHash
|
||||
);
|
||||
|
||||
event LogCancel(
|
||||
address indexed maker,
|
||||
address indexed feeRecipient,
|
||||
bytes makerAssetData,
|
||||
bytes takerAssetData,
|
||||
uint256 makerAssetCancelledAmount,
|
||||
uint256 takerAssetCancelledAmount,
|
||||
bytes32 indexed orderHash
|
||||
);
|
||||
|
||||
function ZRX_TOKEN_CONTRACT()
|
||||
public view
|
||||
returns (address);
|
||||
|
||||
function EXTERNAL_QUERY_GAS_LIMIT()
|
||||
public view
|
||||
returns (uint16);
|
||||
|
||||
function VERSION()
|
||||
public view
|
||||
returns (string);
|
||||
|
||||
function filled(bytes32)
|
||||
public view
|
||||
returns (uint256);
|
||||
|
||||
function cancelled(bytes32)
|
||||
public view
|
||||
returns (uint256);
|
||||
|
||||
/// @dev Calculates the sum of values already filled and cancelled for a given order.
|
||||
/// @param orderHash The Keccak-256 hash of the given order.
|
||||
/// @return Sum of values already filled and cancelled.
|
||||
function getUnavailableTakerAssetAmount(bytes32 orderHash)
|
||||
public view
|
||||
returns (uint256 unavailableTakerAssetAmount);
|
||||
|
||||
/// @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);
|
||||
|
||||
/// @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);
|
||||
|
||||
/// @dev Calculates Keccak-256 hash of order with specified parameters.
|
||||
/// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
|
||||
/// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
|
||||
/// @return Keccak-256 hash of order.
|
||||
function getOrderHash(address[5] orderAddresses, uint256[6] orderValues)
|
||||
public view
|
||||
returns (bytes32 orderHash);
|
||||
|
||||
/// @dev Verifies that an order signature is valid.
|
||||
/// @param signer address of signer.
|
||||
/// @param hash Signed Keccak-256 hash.
|
||||
/// @param v ECDSA signature parameter v.
|
||||
/// @param r ECDSA signature parameters r.
|
||||
/// @param s ECDSA signature parameters s.
|
||||
/// @return Validity of order signature.
|
||||
function isValidSignature(
|
||||
address signer,
|
||||
bytes32 hash,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s)
|
||||
public pure
|
||||
returns (bool isValid);
|
||||
|
||||
/// @dev Fills the input order.
|
||||
/// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
|
||||
/// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to fill.
|
||||
/// @param v ECDSA signature parameter v.
|
||||
/// @param r ECDSA signature parameters r.
|
||||
/// @param s ECDSA signature parameters s.
|
||||
/// @return Total amount of takerAsset filled in trade.
|
||||
function fillOrder(
|
||||
address[5] orderAddresses,
|
||||
uint256[6] orderValues,
|
||||
uint256 takerAssetFillAmount,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s)
|
||||
public
|
||||
returns (uint256 takerAssetFilledAmount);
|
||||
|
||||
/// @dev Cancels the input order.
|
||||
/// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
|
||||
/// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
|
||||
/// @param takerAssetCancelAmount Desired amount of takerAsset to cancel in order.
|
||||
/// @return Amount of takerAsset cancelled.
|
||||
function cancelOrder(
|
||||
address[5] orderAddresses,
|
||||
uint256[6] orderValues,
|
||||
uint256 takerAssetCancelAmount)
|
||||
public
|
||||
returns (uint256 takerAssetCancelledAmount);
|
||||
|
||||
/// @dev Cancels all orders for a specified maker up to a certain time.
|
||||
/// @param salt Orders created with a salt less or equal to this value will be cancelled.
|
||||
function cancelOrdersUpTo(uint256 salt)
|
||||
external;
|
||||
|
||||
/// @dev Fills an order with specified parameters and ECDSA signature. Throws if specified amount not filled entirely.
|
||||
/// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
|
||||
/// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to fill.
|
||||
/// @param v ECDSA signature parameter v.
|
||||
/// @param r ECDSA signature parameters r.
|
||||
/// @param s ECDSA signature parameters s.
|
||||
function fillOrKillOrder(
|
||||
address[5] orderAddresses,
|
||||
uint256[6] orderValues,
|
||||
uint256 takerAssetFillAmount,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s)
|
||||
public;
|
||||
|
||||
/// @dev Fills an order with specified parameters and ECDSA signature. Returns false if the transaction would otherwise revert.
|
||||
/// @param orderAddresses Array of order's maker, taker, makerAsset, takerAsset, and feeRecipient.
|
||||
/// @param orderValues Array of order's makerAssetAmount, takerAssetAmount, makerFee, takerFee, expirationTimestampInSec, and salt.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to fill.
|
||||
/// @param v ECDSA signature parameter v.
|
||||
/// @param r ECDSA signature parameters r.
|
||||
/// @param s ECDSA signature parameters s.
|
||||
/// @return Success if the transaction did not revert.
|
||||
/// @return Total amount of takerAsset filled in trade.
|
||||
function fillOrderNoThrow(
|
||||
address[5] orderAddresses,
|
||||
uint256[6] orderValues,
|
||||
uint256 takerAssetFillAmount,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s)
|
||||
public
|
||||
returns (bool success, uint256 takerAssetFilledAmount);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder in a single transaction.
|
||||
/// @param orderAddresses Array of address arrays containing individual order addresses.
|
||||
/// @param orderValues Array of uint256 arrays containing individual order values.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to fill in orders.
|
||||
/// @param v Array ECDSA signature v parameters.
|
||||
/// @param r Array of ECDSA signature r parameters.
|
||||
/// @param s Array of ECDSA signature s parameters.
|
||||
function batchFillOrders(
|
||||
address[5][] orderAddresses,
|
||||
uint256[6][] orderValues,
|
||||
uint256[] takerAssetFillAmounts,
|
||||
uint8[] v,
|
||||
bytes32[] r,
|
||||
bytes32[] s)
|
||||
external;
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrKill in a single transaction.
|
||||
/// @param orderAddresses Array of address arrays containing individual order addresses.
|
||||
/// @param orderValues Array of uint256 arrays containing individual order values.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to fill in orders.
|
||||
/// @param v Array ECDSA signature v parameters.
|
||||
/// @param r Array of ECDSA signature r parameters.
|
||||
/// @param s Array of ECDSA signature s parameters.
|
||||
function batchFillOrKillOrders(
|
||||
address[5][] orderAddresses,
|
||||
uint256[6][] orderValues,
|
||||
uint256[] takerAssetFillAmounts,
|
||||
uint8[] v,
|
||||
bytes32[] r,
|
||||
bytes32[] s)
|
||||
external;
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrderNoThrow in a single transaction.
|
||||
/// @param orderAddresses Array of address arrays containing individual order addresses.
|
||||
/// @param orderValues Array of uint256 arrays containing individual order values.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to fill in orders.
|
||||
/// @param v Array ECDSA signature v parameters.
|
||||
/// @param r Array of ECDSA signature r parameters.
|
||||
/// @param s Array of ECDSA signature s parameters.
|
||||
function batchFillOrdersNoThrow(
|
||||
address[5][] orderAddresses,
|
||||
uint256[6][] orderValues,
|
||||
uint256[] takerAssetFillAmounts,
|
||||
uint8[] v,
|
||||
bytes32[] r,
|
||||
bytes32[] s)
|
||||
external;
|
||||
|
||||
/// @dev Synchronously executes multiple fill orders in a single transaction until total takerAssetFillAmount filled.
|
||||
/// @param orderAddresses Array of address arrays containing individual order addresses.
|
||||
/// @param orderValues Array of uint256 arrays containing individual order values.
|
||||
/// @param takerAssetFillAmount Desired total amount of takerAsset to fill in orders.
|
||||
/// @param v Array ECDSA signature v parameters.
|
||||
/// @param r Array of ECDSA signature r parameters.
|
||||
/// @param s Array of ECDSA signature s parameters.
|
||||
/// @return Total amount of takerAssetFillAmount filled in orders.
|
||||
function marketFillOrders(
|
||||
address[5][] orderAddresses,
|
||||
uint256[6][] orderValues,
|
||||
uint256 takerAssetFillAmount,
|
||||
uint8[] v,
|
||||
bytes32[] r,
|
||||
bytes32[] s)
|
||||
external
|
||||
returns (uint256 totalTakerAssetFilledAmount);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrderNoThrow in a single transaction until total takerAssetFillAmount filled.
|
||||
/// @param orderAddresses Array of address arrays containing individual order addresses.
|
||||
/// @param orderValues Array of uint256 arrays containing individual order values.
|
||||
/// @param takerAssetFillAmount Desired total amount of takerAsset to fill in orders.
|
||||
/// @param v Array ECDSA signature v parameters.
|
||||
/// @param r Array of ECDSA signature r parameters.
|
||||
/// @param s Array of ECDSA signature s parameters.
|
||||
/// @return Total amount of takerAssetFillAmount filled in orders.
|
||||
function marketFillOrdersNoThrow(
|
||||
address[5][] orderAddresses,
|
||||
uint256[6][] orderValues,
|
||||
uint256 takerAssetFillAmount,
|
||||
uint8[] v,
|
||||
bytes32[] r,
|
||||
bytes32[] s)
|
||||
external
|
||||
returns (uint256 totalTakerAssetFilledAmount);
|
||||
|
||||
/// @dev Synchronously cancels multiple orders in a single transaction.
|
||||
/// @param orderAddresses Array of address arrays containing individual order addresses.
|
||||
/// @param orderValues Array of uint256 arrays containing individual order values.
|
||||
/// @param takerAssetCancelAmounts Array of desired amounts of takerAsset to cancel in orders.
|
||||
function batchCancelOrders(
|
||||
address[5][] orderAddresses,
|
||||
uint256[6][] orderValues,
|
||||
uint256[] takerAssetCancelAmounts)
|
||||
external;
|
||||
}
|
||||
@@ -16,43 +16,21 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "../../utils/Ownable/Ownable.sol";
|
||||
import "../AssetProxy/IAssetProxy.sol";
|
||||
import "../AssetProxy/interfaces/IAssetProxy.sol";
|
||||
import "./libs/LibExchangeErrors.sol";
|
||||
import "./mixins/MAssetProxyDispatcher.sol";
|
||||
|
||||
contract MixinAssetProxyDispatcher is
|
||||
LibExchangeErrors,
|
||||
Ownable,
|
||||
MAssetProxyDispatcher
|
||||
{
|
||||
// Mapping from Asset Proxy Id's to their respective Asset Proxy
|
||||
mapping (uint8 => IAssetProxy) public assetProxies;
|
||||
|
||||
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
|
||||
/// @param assetMetadata Byte array encoded for the respective asset proxy.
|
||||
/// @param from Address to transfer token from.
|
||||
/// @param to Address to transfer token to.
|
||||
/// @param amount Amount of token to transfer.
|
||||
function dispatchTransferFrom(
|
||||
bytes memory assetMetadata,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount)
|
||||
internal
|
||||
{
|
||||
// Do nothing if no amount should be transferred.
|
||||
if (amount > 0) {
|
||||
// Lookup asset proxy.
|
||||
require(assetMetadata.length >= 1);
|
||||
uint8 assetProxyId = uint8(assetMetadata[0]);
|
||||
IAssetProxy assetProxy = assetProxies[assetProxyId];
|
||||
|
||||
// transferFrom will either succeed or throw.
|
||||
assetProxy.transferFrom(assetMetadata, from, to, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Registers an asset proxy to an asset proxy id.
|
||||
/// An id can only be assigned to a single proxy at a given time.
|
||||
/// @param assetProxyId Id to register`newAssetProxy` under.
|
||||
@@ -65,15 +43,21 @@ contract MixinAssetProxyDispatcher is
|
||||
external
|
||||
onlyOwner
|
||||
{
|
||||
// Ensure the existing asset proxy is not unintentionally overwritten.
|
||||
require(oldAssetProxy == address(assetProxies[assetProxyId]));
|
||||
// Ensure the existing asset proxy is not unintentionally overwritten
|
||||
require(
|
||||
oldAssetProxy == address(assetProxies[assetProxyId]),
|
||||
OLD_ASSET_PROXY_MISMATCH
|
||||
);
|
||||
|
||||
IAssetProxy assetProxy = IAssetProxy(newAssetProxy);
|
||||
|
||||
// Ensure that the id of newAssetProxy matches the passed in assetProxyId, unless it is being reset to 0.
|
||||
if (newAssetProxy != address(0)) {
|
||||
uint8 newAssetProxyId = assetProxy.getProxyId();
|
||||
require(newAssetProxyId == assetProxyId);
|
||||
require(
|
||||
newAssetProxyId == assetProxyId,
|
||||
NEW_ASSET_PROXY_MISMATCH
|
||||
);
|
||||
}
|
||||
|
||||
// Add asset proxy and log registration.
|
||||
@@ -89,7 +73,34 @@ contract MixinAssetProxyDispatcher is
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
IAssetProxy assetProxy = assetProxies[assetProxyId];
|
||||
return address(assetProxy);
|
||||
address assetProxy = address(assetProxies[assetProxyId]);
|
||||
return assetProxy;
|
||||
}
|
||||
|
||||
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
|
||||
/// @param assetMetadata Byte array encoded for the respective asset proxy.
|
||||
/// @param from Address to transfer token from.
|
||||
/// @param to Address to transfer token to.
|
||||
/// @param amount Amount of token to transfer.
|
||||
function dispatchTransferFrom(
|
||||
bytes memory assetMetadata,
|
||||
address from,
|
||||
address to,
|
||||
uint256 amount)
|
||||
internal
|
||||
{
|
||||
// Do nothing if no amount should be transferred.
|
||||
if (amount > 0) {
|
||||
// Lookup asset proxy
|
||||
require(
|
||||
assetMetadata.length >= 1,
|
||||
GT_ZERO_LENGTH_REQUIRED
|
||||
);
|
||||
uint8 assetProxyId = uint8(assetMetadata[0]);
|
||||
IAssetProxy assetProxy = assetProxies[assetProxyId];
|
||||
|
||||
// transferFrom will either succeed or throw.
|
||||
assetProxy.transferFrom(assetMetadata, from, to, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,26 +16,23 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./LibFillResults.sol";
|
||||
import "./LibOrder.sol";
|
||||
import "./LibErrors.sol";
|
||||
import "./LibMath.sol";
|
||||
import "./libs/LibFillResults.sol";
|
||||
import "./libs/LibOrder.sol";
|
||||
import "./libs/LibMath.sol";
|
||||
import "./libs/LibExchangeErrors.sol";
|
||||
import "./mixins/MExchangeCore.sol";
|
||||
import "./mixins/MSettlement.sol";
|
||||
import "./mixins/MSignatureValidator.sol";
|
||||
import "./mixins/MTransactions.sol";
|
||||
|
||||
/// @dev Provides MExchangeCore
|
||||
/// @dev Consumes MSettlement
|
||||
/// @dev Consumes MSignatureValidator
|
||||
contract MixinExchangeCore is
|
||||
LibOrder,
|
||||
LibFillResults,
|
||||
LibErrors,
|
||||
LibMath,
|
||||
LibExchangeErrors,
|
||||
MExchangeCore,
|
||||
MSettlement,
|
||||
MSignatureValidator,
|
||||
@@ -51,35 +48,19 @@ contract MixinExchangeCore is
|
||||
// Orders with a salt less than their maker's epoch are considered cancelled
|
||||
mapping (address => uint256) public makerEpoch;
|
||||
|
||||
event Fill(
|
||||
address indexed makerAddress,
|
||||
address takerAddress,
|
||||
address indexed feeRecipientAddress,
|
||||
uint256 makerAssetFilledAmount,
|
||||
uint256 takerAssetFilledAmount,
|
||||
uint256 makerFeePaid,
|
||||
uint256 takerFeePaid,
|
||||
bytes32 indexed orderHash,
|
||||
bytes makerAssetData,
|
||||
bytes takerAssetData
|
||||
);
|
||||
|
||||
event Cancel(
|
||||
address indexed makerAddress,
|
||||
address indexed feeRecipientAddress,
|
||||
bytes32 indexed orderHash,
|
||||
bytes makerAssetData,
|
||||
bytes takerAssetData
|
||||
);
|
||||
|
||||
event CancelUpTo(
|
||||
address indexed makerAddress,
|
||||
uint256 makerEpoch
|
||||
);
|
||||
|
||||
/*
|
||||
* Core exchange functions
|
||||
*/
|
||||
/// @dev Cancels all orders reated by sender with a salt less than or equal to the specified salt value.
|
||||
/// @param salt Orders created with a salt less or equal to this value will be cancelled.
|
||||
function cancelOrdersUpTo(uint256 salt)
|
||||
external
|
||||
{
|
||||
uint256 newMakerEpoch = salt + 1; // makerEpoch is initialized to 0, so to cancelUpTo we need salt + 1
|
||||
require(
|
||||
newMakerEpoch > makerEpoch[msg.sender], // epoch must be monotonically increasing
|
||||
INVALID_NEW_MAKER_EPOCH
|
||||
);
|
||||
makerEpoch[msg.sender] = newMakerEpoch;
|
||||
emit CancelUpTo(msg.sender, newMakerEpoch);
|
||||
}
|
||||
|
||||
/// @dev Fills the input order.
|
||||
/// @param order Order struct containing order specifications.
|
||||
@@ -111,22 +92,40 @@ contract MixinExchangeCore is
|
||||
// Validate order and maker only if first time seen
|
||||
// TODO: Read filled and cancelled only once
|
||||
if (filled[orderHash] == 0) {
|
||||
require(order.makerAssetAmount > 0);
|
||||
require(order.takerAssetAmount > 0);
|
||||
require(isValidSignature(orderHash, order.makerAddress, signature));
|
||||
require(
|
||||
order.makerAssetAmount > 0,
|
||||
GT_ZERO_AMOUNT_REQUIRED
|
||||
);
|
||||
require(
|
||||
order.takerAssetAmount > 0,
|
||||
GT_ZERO_AMOUNT_REQUIRED
|
||||
);
|
||||
require(
|
||||
isValidSignature(orderHash, order.makerAddress, signature),
|
||||
SIGNATURE_VALIDATION_FAILED
|
||||
);
|
||||
}
|
||||
|
||||
// Validate sender is allowed to fill this order
|
||||
if (order.senderAddress != address(0)) {
|
||||
require(order.senderAddress == msg.sender);
|
||||
require(
|
||||
order.senderAddress == msg.sender,
|
||||
INVALID_SENDER
|
||||
);
|
||||
}
|
||||
|
||||
// Validate taker is allowed to fill this order
|
||||
address takerAddress = getCurrentContextAddress();
|
||||
if (order.takerAddress != address(0)) {
|
||||
require(order.takerAddress == takerAddress);
|
||||
require(
|
||||
order.takerAddress == takerAddress,
|
||||
INVALID_CONTEXT
|
||||
);
|
||||
}
|
||||
require(takerAssetFillAmount > 0);
|
||||
require(
|
||||
takerAssetFillAmount > 0,
|
||||
GT_ZERO_AMOUNT_REQUIRED
|
||||
);
|
||||
|
||||
// Validate order expiration
|
||||
if (block.timestamp >= order.expirationTimeSeconds) {
|
||||
@@ -173,17 +172,29 @@ contract MixinExchangeCore is
|
||||
bytes32 orderHash = getOrderHash(order);
|
||||
|
||||
// Validate the order
|
||||
require(order.makerAssetAmount > 0);
|
||||
require(order.takerAssetAmount > 0);
|
||||
require(
|
||||
order.makerAssetAmount > 0,
|
||||
GT_ZERO_AMOUNT_REQUIRED
|
||||
);
|
||||
require(
|
||||
order.takerAssetAmount > 0,
|
||||
GT_ZERO_AMOUNT_REQUIRED
|
||||
);
|
||||
|
||||
// Validate sender is allowed to cancel this order
|
||||
if (order.senderAddress != address(0)) {
|
||||
require(order.senderAddress == msg.sender);
|
||||
require(
|
||||
order.senderAddress == msg.sender,
|
||||
INVALID_SENDER
|
||||
);
|
||||
}
|
||||
|
||||
// Validate transaction signed by maker
|
||||
address makerAddress = getCurrentContextAddress();
|
||||
require(order.makerAddress == makerAddress);
|
||||
require(
|
||||
order.makerAddress == makerAddress,
|
||||
INVALID_CONTEXT
|
||||
);
|
||||
|
||||
if (block.timestamp >= order.expirationTimeSeconds) {
|
||||
emit ExchangeError(uint8(Errors.ORDER_EXPIRED), orderHash);
|
||||
@@ -207,16 +218,6 @@ contract MixinExchangeCore is
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @param salt Orders created with a salt less or equal to this value will be cancelled.
|
||||
function cancelOrdersUpTo(uint256 salt)
|
||||
external
|
||||
{
|
||||
uint256 newMakerEpoch = salt + 1; // makerEpoch is initialized to 0, so to cancelUpTo we need salt+1
|
||||
require(newMakerEpoch > makerEpoch[msg.sender]); // epoch must be monotonically increasing
|
||||
makerEpoch[msg.sender] = newMakerEpoch;
|
||||
emit CancelUpTo(msg.sender, newMakerEpoch);
|
||||
}
|
||||
|
||||
/// @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(
|
||||
|
||||
@@ -16,23 +16,24 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "./mixins/MSettlement.sol";
|
||||
import "./mixins/MAssetProxyDispatcher.sol";
|
||||
import "./LibOrder.sol";
|
||||
import "./LibMath.sol";
|
||||
import "../AssetProxy/IAssetProxy.sol";
|
||||
import "./libs/LibOrder.sol";
|
||||
import "./libs/LibMath.sol";
|
||||
|
||||
/// @dev Provides MixinSettlement
|
||||
contract MixinSettlement is
|
||||
LibMath,
|
||||
MSettlement,
|
||||
MAssetProxyDispatcher
|
||||
{
|
||||
// ZRX metadata used for fee transfers.
|
||||
// This will be constant throughout the life of the Exchange contract,
|
||||
// since ZRX will always be transferred via the ERC20 AssetProxy.
|
||||
bytes internal ZRX_PROXY_DATA;
|
||||
|
||||
/// @dev Gets the ZRX metadata used for fee transfers.
|
||||
function zrxProxyData()
|
||||
external
|
||||
view
|
||||
@@ -41,12 +42,20 @@ contract MixinSettlement is
|
||||
return ZRX_PROXY_DATA;
|
||||
}
|
||||
|
||||
function MixinSettlement(bytes memory _zrxProxyData)
|
||||
/// TODO: _zrxProxyData should be a constant in production.
|
||||
/// @dev Constructor sets the metadata that will be used for paying ZRX fees.
|
||||
/// @param _zrxProxyData Byte array containing ERC20 proxy id concatenated with address of ZRX.
|
||||
constructor (bytes memory _zrxProxyData)
|
||||
public
|
||||
{
|
||||
ZRX_PROXY_DATA = _zrxProxyData;
|
||||
}
|
||||
|
||||
/// @dev Settles an order by transferring assets between counterparties.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAddress Address selling takerAsset and buying makerAsset.
|
||||
/// @param takerAssetFilledAmount The amount of takerAsset that will be transferred to the order's maker.
|
||||
/// @return Amount filled by maker and fees paid by maker/taker.
|
||||
function settleOrder(
|
||||
LibOrder.Order memory order,
|
||||
address takerAddress,
|
||||
|
||||
@@ -16,29 +16,39 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "./mixins/MSignatureValidator.sol";
|
||||
import "./ISigner.sol";
|
||||
import "./interfaces/ISigner.sol";
|
||||
import "./libs/LibExchangeErrors.sol";
|
||||
import "../../utils/LibBytes/LibBytes.sol";
|
||||
|
||||
/// @dev Provides MSignatureValidator
|
||||
contract MixinSignatureValidator is MSignatureValidator {
|
||||
|
||||
enum SignatureType {
|
||||
Illegal, // Default value
|
||||
Invalid,
|
||||
Caller,
|
||||
Ecrecover,
|
||||
EIP712,
|
||||
Trezor,
|
||||
Contract,
|
||||
PreSigned
|
||||
}
|
||||
contract MixinSignatureValidator is
|
||||
LibBytes,
|
||||
LibExchangeErrors,
|
||||
MSignatureValidator
|
||||
{
|
||||
|
||||
// Mapping of hash => signer => signed
|
||||
mapping(bytes32 => mapping(address => bool)) preSigned;
|
||||
|
||||
/// @dev Approves a hash on-chain using any valid signature type.
|
||||
/// After presigning a hash, the preSign signature type will become valid for that hash and signer.
|
||||
/// @param signer Address that should have signed the given hash.
|
||||
/// @param signature Proof that the hash has been signed by signer.
|
||||
function preSign(
|
||||
bytes32 hash,
|
||||
address signer,
|
||||
bytes signature)
|
||||
external
|
||||
{
|
||||
require(
|
||||
isValidSignature(hash, signer, signature),
|
||||
SIGNATURE_VALIDATION_FAILED
|
||||
);
|
||||
preSigned[hash][signer] = true;
|
||||
}
|
||||
|
||||
/// @dev Verifies that a hash has been signed by the given signer.
|
||||
/// @param hash Any 32 byte hash.
|
||||
/// @param signer Address that should have signed the given hash.
|
||||
@@ -54,7 +64,10 @@ contract MixinSignatureValidator is MSignatureValidator {
|
||||
{
|
||||
// TODO: Domain separation: make hash depend on role. (Taker sig should not be valid as maker sig, etc.)
|
||||
|
||||
require(signature.length >= 1);
|
||||
require(
|
||||
signature.length >= 1,
|
||||
INVALID_SIGNATURE_LENGTH
|
||||
);
|
||||
SignatureType signatureType = SignatureType(uint8(signature[0]));
|
||||
|
||||
// Variables are not scoped in Solidity
|
||||
@@ -69,14 +82,18 @@ contract MixinSignatureValidator is MSignatureValidator {
|
||||
// it an explicit option. This aids testing and analysis. It is
|
||||
// also the initialization value for the enum type.
|
||||
if (signatureType == SignatureType.Illegal) {
|
||||
revert();
|
||||
// NOTE: Reason cannot be assigned to a variable because of https://github.com/ethereum/solidity/issues/4051
|
||||
revert("Illegal signature type.");
|
||||
|
||||
// Always invalid signature
|
||||
// Like Illegal, this is always implicitly available and therefore
|
||||
// offered explicitly. It can be implicitly created by providing
|
||||
// a correctly formatted but incorrect signature.
|
||||
} else if (signatureType == SignatureType.Invalid) {
|
||||
require(signature.length == 1);
|
||||
require(
|
||||
signature.length == 1,
|
||||
INVALID_SIGNATURE_LENGTH
|
||||
);
|
||||
isValid = false;
|
||||
return isValid;
|
||||
|
||||
@@ -89,16 +106,22 @@ contract MixinSignatureValidator is MSignatureValidator {
|
||||
// `Caller` for his own signature. Or A and C can sign and B can
|
||||
// submit using `Caller`. Having `Caller` allows this flexibility.
|
||||
} else if (signatureType == SignatureType.Caller) {
|
||||
require(signature.length == 1);
|
||||
require(
|
||||
signature.length == 1,
|
||||
INVALID_SIGNATURE_LENGTH
|
||||
);
|
||||
isValid = signer == msg.sender;
|
||||
return isValid;
|
||||
|
||||
// Signed using web3.eth_sign
|
||||
} else if (signatureType == SignatureType.Ecrecover) {
|
||||
require(signature.length == 66);
|
||||
require(
|
||||
signature.length == 66,
|
||||
INVALID_SIGNATURE_LENGTH
|
||||
);
|
||||
v = uint8(signature[1]);
|
||||
r = get32(signature, 2);
|
||||
s = get32(signature, 34);
|
||||
r = readBytes32(signature, 2);
|
||||
s = readBytes32(signature, 34);
|
||||
recovered = ecrecover(
|
||||
keccak256("\x19Ethereum Signed Message:\n32", hash),
|
||||
v,
|
||||
@@ -110,10 +133,13 @@ contract MixinSignatureValidator is MSignatureValidator {
|
||||
|
||||
// Signature using EIP712
|
||||
} else if (signatureType == SignatureType.EIP712) {
|
||||
require(signature.length == 66);
|
||||
require(
|
||||
signature.length == 66,
|
||||
INVALID_SIGNATURE_LENGTH
|
||||
);
|
||||
v = uint8(signature[1]);
|
||||
r = get32(signature, 2);
|
||||
s = get32(signature, 34);
|
||||
r = readBytes32(signature, 2);
|
||||
s = readBytes32(signature, 34);
|
||||
recovered = ecrecover(hash, v, r, s);
|
||||
isValid = signer == recovered;
|
||||
return isValid;
|
||||
@@ -127,10 +153,13 @@ contract MixinSignatureValidator is MSignatureValidator {
|
||||
// https://github.com/trezor/trezor-mcu/blob/master/firmware/ethereum.c#L602
|
||||
// https://github.com/trezor/trezor-mcu/blob/master/firmware/crypto.c#L36
|
||||
} else if (signatureType == SignatureType.Trezor) {
|
||||
require(signature.length == 66);
|
||||
require(
|
||||
signature.length == 66,
|
||||
INVALID_SIGNATURE_LENGTH
|
||||
);
|
||||
v = uint8(signature[1]);
|
||||
r = get32(signature, 2);
|
||||
s = get32(signature, 34);
|
||||
r = readBytes32(signature, 2);
|
||||
s = readBytes32(signature, 34);
|
||||
recovered = ecrecover(
|
||||
keccak256("\x19Ethereum Signed Message:\n\x41", hash),
|
||||
v,
|
||||
@@ -156,37 +185,7 @@ contract MixinSignatureValidator is MSignatureValidator {
|
||||
// that we currently support. In this case returning false
|
||||
// may lead the caller to incorrectly believe that the
|
||||
// signature was invalid.)
|
||||
revert();
|
||||
// NOTE: Reason cannot be assigned to a variable because of https://github.com/ethereum/solidity/issues/4051
|
||||
revert("Unsupported signature type.");
|
||||
}
|
||||
|
||||
/// @dev Approves a hash on-chain using any valid signature type.
|
||||
/// After presigning a hash, the preSign signature type will become valid for that hash and signer.
|
||||
/// @param signer Address that should have signed the given hash.
|
||||
/// @param signature Proof that the hash has been signed by signer.
|
||||
function preSign(
|
||||
bytes32 hash,
|
||||
address signer,
|
||||
bytes signature)
|
||||
external
|
||||
{
|
||||
require(isValidSignature(hash, signer, signature));
|
||||
preSigned[hash][signer] = true;
|
||||
}
|
||||
|
||||
function get32(bytes memory b, uint256 index)
|
||||
private pure
|
||||
returns (bytes32 result)
|
||||
{
|
||||
require(b.length >= index + 32);
|
||||
|
||||
// Arrays are prefixed by a 256 bit length parameter
|
||||
index += 32;
|
||||
|
||||
// Read the bytes32 from array memory
|
||||
assembly {
|
||||
result := mload(add(b, index))
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,12 +16,13 @@
|
||||
|
||||
*/
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./mixins/MSignatureValidator.sol";
|
||||
import "./mixins/MTransactions.sol";
|
||||
import "./libs/LibExchangeErrors.sol";
|
||||
|
||||
contract MixinTransactions is
|
||||
LibExchangeErrors,
|
||||
MSignatureValidator,
|
||||
MTransactions
|
||||
{
|
||||
@@ -56,12 +57,18 @@ contract MixinTransactions is
|
||||
);
|
||||
|
||||
// Validate transaction has not been executed
|
||||
require(!transactions[transactionHash]);
|
||||
require(
|
||||
!transactions[transactionHash],
|
||||
DUPLICATE_TRANSACTION_HASH
|
||||
);
|
||||
|
||||
// TODO: is SignatureType.Caller necessary if we make this check?
|
||||
if (signer != msg.sender) {
|
||||
// Validate signature
|
||||
require(isValidSignature(transactionHash, signer, signature));
|
||||
require(
|
||||
isValidSignature(transactionHash, signer, signature),
|
||||
SIGNATURE_VALIDATION_FAILED
|
||||
);
|
||||
|
||||
// Set the current transaction signer
|
||||
currentContextAddress = signer;
|
||||
@@ -69,7 +76,10 @@ contract MixinTransactions is
|
||||
|
||||
// Execute transaction
|
||||
transactions[transactionHash] = true;
|
||||
require(address(this).delegatecall(data));
|
||||
require(
|
||||
address(this).delegatecall(data),
|
||||
TRANSACTION_EXECUTION_FAILED
|
||||
);
|
||||
|
||||
// Reset current transaction signer
|
||||
// TODO: Check if gas is paid when currentContextAddress is already 0.
|
||||
|
||||
@@ -16,21 +16,22 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../utils/LibBytes/LibBytes.sol";
|
||||
import "./mixins/MExchangeCore.sol";
|
||||
import "./LibMath.sol";
|
||||
import "./LibOrder.sol";
|
||||
import "./LibFillResults.sol";
|
||||
import "./libs/LibMath.sol";
|
||||
import "./libs/LibOrder.sol";
|
||||
import "./libs/LibFillResults.sol";
|
||||
import "./libs/LibExchangeErrors.sol";
|
||||
|
||||
/// @dev Consumes MExchangeCore
|
||||
contract MixinWrapperFunctions is
|
||||
LibOrder,
|
||||
LibFillResults,
|
||||
LibMath,
|
||||
LibBytes,
|
||||
LibExchangeErrors,
|
||||
MExchangeCore
|
||||
{
|
||||
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
|
||||
@@ -49,7 +50,10 @@ contract MixinWrapperFunctions is
|
||||
takerAssetFillAmount,
|
||||
signature
|
||||
);
|
||||
require(fillResults.takerAssetFilledAmount == takerAssetFillAmount);
|
||||
require(
|
||||
fillResults.takerAssetFilledAmount == takerAssetFillAmount,
|
||||
COMPLETE_FILL_FAILED
|
||||
);
|
||||
return fillResults;
|
||||
}
|
||||
|
||||
@@ -327,7 +331,11 @@ contract MixinWrapperFunctions is
|
||||
for (uint256 i = 0; i < orders.length; i++) {
|
||||
|
||||
// Token being sold by taker must be the same for each order
|
||||
require(areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData));
|
||||
// TODO: optimize by only using takerAssetData for first order.
|
||||
require(
|
||||
areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData),
|
||||
ASSET_DATA_MISMATCH
|
||||
);
|
||||
|
||||
// Calculate the remaining amount of takerAsset to sell
|
||||
uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);
|
||||
@@ -366,7 +374,11 @@ contract MixinWrapperFunctions is
|
||||
for (uint256 i = 0; i < orders.length; i++) {
|
||||
|
||||
// Token being sold by taker must be the same for each order
|
||||
require(areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData));
|
||||
// TODO: optimize by only using takerAssetData for first order.
|
||||
require(
|
||||
areBytesEqual(orders[i].takerAssetData, orders[0].takerAssetData),
|
||||
ASSET_DATA_MISMATCH
|
||||
);
|
||||
|
||||
// Calculate the remaining amount of takerAsset to sell
|
||||
uint256 remainingTakerAssetFillAmount = safeSub(takerAssetFillAmount, totalFillResults.takerAssetFilledAmount);
|
||||
@@ -404,7 +416,11 @@ contract MixinWrapperFunctions is
|
||||
for (uint256 i = 0; i < orders.length; i++) {
|
||||
|
||||
// Token being bought by taker must be the same for each order
|
||||
require(areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData));
|
||||
// TODO: optimize by only using makerAssetData for first order.
|
||||
require(
|
||||
areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData),
|
||||
ASSET_DATA_MISMATCH
|
||||
);
|
||||
|
||||
// Calculate the remaining amount of makerAsset to buy
|
||||
uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);
|
||||
@@ -451,7 +467,11 @@ contract MixinWrapperFunctions is
|
||||
for (uint256 i = 0; i < orders.length; i++) {
|
||||
|
||||
// Token being bought by taker must be the same for each order
|
||||
require(areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData));
|
||||
// TODO: optimize by only using makerAssetData for first order.
|
||||
require(
|
||||
areBytesEqual(orders[i].makerAssetData, orders[0].makerAssetData),
|
||||
ASSET_DATA_MISMATCH
|
||||
);
|
||||
|
||||
// Calculate the remaining amount of makerAsset to buy
|
||||
uint256 remainingMakerAssetFillAmount = safeSub(makerAssetFillAmount, totalFillResults.makerAssetFilledAmount);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
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.23;
|
||||
|
||||
contract IAssetProxyDispatcher {
|
||||
|
||||
/// @dev Registers an asset proxy to an asset proxy id.
|
||||
/// An id can only be assigned to a single proxy at a given time.
|
||||
/// @param assetProxyId Id to register`newAssetProxy` under.
|
||||
/// @param newAssetProxy Address of new asset proxy to register, or 0x0 to unset assetProxyId.
|
||||
/// @param oldAssetProxy Existing asset proxy to overwrite, or 0x0 if assetProxyId is currently unused.
|
||||
function registerAssetProxy(
|
||||
uint8 assetProxyId,
|
||||
address newAssetProxy,
|
||||
address oldAssetProxy)
|
||||
external;
|
||||
|
||||
/// @dev Gets an asset proxy.
|
||||
/// @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
|
||||
returns (address);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
|
||||
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.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./IExchangeCore.sol";
|
||||
import "./ISignatureValidator.sol";
|
||||
import "./IAssetProxyDispatcher.sol";
|
||||
import "./ITransactions.sol";
|
||||
import "./IWrapperFunctions.sol";
|
||||
|
||||
contract IExchange is
|
||||
IWrapperFunctions,
|
||||
IExchangeCore,
|
||||
ISignatureValidator,
|
||||
ITransactions,
|
||||
IAssetProxyDispatcher
|
||||
{}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
|
||||
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.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../libs/LibOrder.sol";
|
||||
import "../libs/LibFillResults.sol";
|
||||
|
||||
contract IExchangeCore {
|
||||
|
||||
/// @dev Cancels all orders reated by sender with a salt less than or equal to the specified salt value.
|
||||
/// @param salt Orders created with a salt less or equal to this value will be cancelled.
|
||||
function cancelOrdersUpTo(uint256 salt)
|
||||
external;
|
||||
|
||||
/// @dev Fills the input order.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
/// @return Amounts filled and fees paid by maker and taker.
|
||||
function fillOrder(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory fillResults);
|
||||
|
||||
/// @dev After calling, the order can not be filled anymore.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @return True if the order state changed to cancelled.
|
||||
/// False if the transaction was already cancelled or expired.
|
||||
function cancelOrder(LibOrder.Order memory order)
|
||||
public
|
||||
returns (bool);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
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.23;
|
||||
|
||||
contract ISignatureValidator {
|
||||
|
||||
/// @dev Approves a hash on-chain using any valid signature type.
|
||||
/// After presigning a hash, the preSign signature type will become valid for that hash and signer.
|
||||
/// @param signer Address that should have signed the given hash.
|
||||
/// @param signature Proof that the hash has been signed by signer.
|
||||
function preSign(
|
||||
bytes32 hash,
|
||||
address signer,
|
||||
bytes signature)
|
||||
external;
|
||||
}
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
contract ISigner {
|
||||
|
||||
/// @dev Verifies that a signature is valid.
|
||||
/// @param hash Message hash that is signed.
|
||||
/// @param signature Proof of signing.
|
||||
/// @return Validity of order signature.
|
||||
function isValidSignature(
|
||||
bytes32 hash,
|
||||
bytes signature)
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
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.23;
|
||||
|
||||
contract ITransactions {
|
||||
|
||||
/// @dev Executes an exchange method call in the context of signer.
|
||||
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.
|
||||
/// @param signer Address of transaction signer.
|
||||
/// @param data AbiV2 encoded calldata.
|
||||
/// @param signature Proof of signer transaction by signer.
|
||||
function executeTransaction(
|
||||
uint256 salt,
|
||||
address signer,
|
||||
bytes data,
|
||||
bytes signature)
|
||||
external;
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
|
||||
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.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./libs/LibOrder.sol";
|
||||
import "./libs/LibFillResults.sol";
|
||||
|
||||
contract IWrapperFunctions is
|
||||
LibOrder,
|
||||
LibFillResults,
|
||||
LibMath,
|
||||
LibBytes,
|
||||
LibExchangeErrors,
|
||||
MExchangeCore
|
||||
{
|
||||
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
|
||||
/// @param order LibOrder.Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
function fillOrKillOrder(
|
||||
LibOrder.LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature)
|
||||
public
|
||||
returns (LibFillResults.LibFillResults.FillResults memory fillResults);
|
||||
|
||||
/// @dev Fills an order with specified parameters and ECDSA signature.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param order LibOrder.Order struct containing order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signature Proof that order has been created by maker.
|
||||
/// @return Amounts filled and fees paid by maker and taker.
|
||||
function fillOrderNoThrow(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory fillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
function batchFillOrders(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures)
|
||||
public;
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrKill.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
function batchFillOrKillOrders(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures)
|
||||
public;
|
||||
|
||||
/// @dev Fills an order with specified parameters and ECDSA signature.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
function batchFillOrdersNoThrow(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256[] memory takerAssetFillAmounts,
|
||||
bytes[] memory signatures)
|
||||
public;
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signatures Proofs that orders have been created by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketSellOrders(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes[] memory signatures)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketSellOrdersNoThrow(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes[] memory signatures)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple calls of fillOrder until total amount of makerAsset is bought by taker.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to buy.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketBuyOrders(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously executes multiple fill orders in a single transaction until total amount is bought by taker.
|
||||
/// Returns false if the transaction would otherwise revert.
|
||||
/// @param orders Array of order specifications.
|
||||
/// @param makerAssetFillAmount Desired amount of makerAsset to buy.
|
||||
/// @param signatures Proofs that orders have been signed by makers.
|
||||
/// @return Amounts filled and fees paid by makers and taker.
|
||||
function marketBuyOrdersNoThrow(
|
||||
LibOrder.Order[] memory orders,
|
||||
uint256 makerAssetFillAmount,
|
||||
bytes[] memory signatures)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory totalFillResults);
|
||||
|
||||
/// @dev Synchronously cancels multiple orders in a single transaction.
|
||||
/// @param orders Array of order specifications.
|
||||
function batchCancelOrders(LibOrder.Order[] memory orders)
|
||||
public;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
|
||||
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.23;
|
||||
|
||||
contract LibExchangeErrors {
|
||||
|
||||
// Error Codes
|
||||
enum Errors {
|
||||
ORDER_EXPIRED, // Order has already expired
|
||||
ORDER_FULLY_FILLED, // Order has already been fully filled
|
||||
ORDER_CANCELLED, // Order has already been cancelled
|
||||
ROUNDING_ERROR_TOO_LARGE, // Rounding error too large
|
||||
INSUFFICIENT_BALANCE_OR_ALLOWANCE // Insufficient balance or allowance for token transfer
|
||||
}
|
||||
|
||||
event ExchangeError(uint8 indexed errorId, bytes32 indexed orderHash);
|
||||
|
||||
// Core revert reasons
|
||||
string constant GT_ZERO_AMOUNT_REQUIRED = "Amount must be greater than 0.";
|
||||
string constant SIGNATURE_VALIDATION_FAILED = "Signature validation failed.";
|
||||
string constant INVALID_SENDER = "Invalid `msg.sender`.";
|
||||
string constant INVALID_CONTEXT = "Function called in an invalid context.";
|
||||
string constant INVALID_NEW_MAKER_EPOCH = "Specified salt must be greater than or equal to existing makerEpoch.";
|
||||
|
||||
// Transaction revert reasons
|
||||
string constant DUPLICATE_TRANSACTION_HASH = "Transaction has already been executed.";
|
||||
string constant TRANSACTION_EXECUTION_FAILED = "Transaction execution failed.";
|
||||
|
||||
// Wrapper revert reasons
|
||||
string constant COMPLETE_FILL_FAILED = "Desired fill amount could not be completely filled.";
|
||||
string constant ASSET_DATA_MISMATCH = "Asset data must be the same for each order.";
|
||||
|
||||
// Asset proxy dispatcher revert reasons
|
||||
string constant GT_ZERO_LENGTH_REQUIRED = "Length must be greater than 0.";
|
||||
string constant OLD_ASSET_PROXY_MISMATCH = "Old asset proxy does not match asset proxy at given id.";
|
||||
string constant NEW_ASSET_PROXY_MISMATCH = "New asset proxy id does not match given id.";
|
||||
|
||||
// Signature validator revert reasons
|
||||
string constant INVALID_SIGNATURE_LENGTH = "Invalid signature length.";
|
||||
string constant ILLEGAL_SIGNATURE_TYPE = "Illegal signature type.";
|
||||
string constant UNSUPPORTED_SIGNATURE_TYPE = "Unsupported signature type.";
|
||||
}
|
||||
@@ -16,12 +16,13 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "../../utils/SafeMath/SafeMath.sol";
|
||||
import "../../../utils/SafeMath/SafeMath.sol";
|
||||
|
||||
contract LibFillResults is SafeMath {
|
||||
contract LibFillResults is
|
||||
SafeMath
|
||||
{
|
||||
|
||||
struct FillResults {
|
||||
uint256 makerAssetFilledAmount;
|
||||
@@ -16,12 +16,13 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "../../utils/SafeMath/SafeMath.sol";
|
||||
import "../../../utils/SafeMath/SafeMath.sol";
|
||||
|
||||
contract LibMath is SafeMath {
|
||||
contract LibMath is
|
||||
SafeMath
|
||||
{
|
||||
|
||||
/// @dev Calculates partial value given a numerator and denominator.
|
||||
/// @param numerator Numerator.
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
contract LibOrder {
|
||||
|
||||
@@ -16,9 +16,13 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
contract MAssetProxyDispatcher {
|
||||
import "../interfaces/IAssetProxyDispatcher.sol";
|
||||
|
||||
contract MAssetProxyDispatcher is
|
||||
IAssetProxyDispatcher
|
||||
{
|
||||
|
||||
// Logs registration of new asset proxy
|
||||
event AssetProxySet(
|
||||
@@ -38,23 +42,4 @@ contract MAssetProxyDispatcher {
|
||||
address to,
|
||||
uint256 amount)
|
||||
internal;
|
||||
|
||||
/// @dev Registers an asset proxy to an asset proxy id.
|
||||
/// An id can only be assigned to a single proxy at a given time.
|
||||
/// @param assetProxyId Id to register`newAssetProxy` under.
|
||||
/// @param newAssetProxy Address of new asset proxy to register, or 0x0 to unset assetProxyId.
|
||||
/// @param oldAssetProxy Existing asset proxy to overwrite, or 0x0 if assetProxyId is currently unused.
|
||||
function registerAssetProxy(
|
||||
uint8 assetProxyId,
|
||||
address newAssetProxy,
|
||||
address oldAssetProxy)
|
||||
external;
|
||||
|
||||
/// @dev Gets an asset proxy.
|
||||
/// @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
|
||||
returns (address);
|
||||
}
|
||||
|
||||
@@ -16,25 +16,51 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "../LibOrder.sol";
|
||||
import "../LibFillResults.sol";
|
||||
import "../libs/LibOrder.sol";
|
||||
import "../libs/LibFillResults.sol";
|
||||
import "../interfaces/IExchangeCore.sol";
|
||||
|
||||
contract MExchangeCore {
|
||||
contract MExchangeCore is
|
||||
IExchangeCore
|
||||
{
|
||||
|
||||
function fillOrder(
|
||||
// Fill event is emitted whenever an order is filled.
|
||||
event Fill(
|
||||
address indexed makerAddress,
|
||||
address takerAddress,
|
||||
address indexed feeRecipientAddress,
|
||||
uint256 makerAssetFilledAmount,
|
||||
uint256 takerAssetFilledAmount,
|
||||
uint256 makerFeePaid,
|
||||
uint256 takerFeePaid,
|
||||
bytes32 indexed orderHash,
|
||||
bytes makerAssetData,
|
||||
bytes takerAssetData
|
||||
);
|
||||
|
||||
// Cancel event is emitted whenever an individual order is cancelled.
|
||||
event Cancel(
|
||||
address indexed makerAddress,
|
||||
address indexed feeRecipientAddress,
|
||||
bytes32 indexed orderHash,
|
||||
bytes makerAssetData,
|
||||
bytes takerAssetData
|
||||
);
|
||||
|
||||
// CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully.
|
||||
event CancelUpTo(
|
||||
address indexed makerAddress,
|
||||
uint256 makerEpoch
|
||||
);
|
||||
|
||||
/// @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(
|
||||
LibOrder.Order memory order,
|
||||
uint256 takerAssetFillAmount,
|
||||
bytes memory signature)
|
||||
public
|
||||
returns (LibFillResults.FillResults memory fillResults);
|
||||
|
||||
function cancelOrder(LibOrder.Order memory order)
|
||||
public
|
||||
returns (bool);
|
||||
|
||||
function cancelOrdersUpTo(uint256 salt)
|
||||
external;
|
||||
address takerAddress,
|
||||
bytes32 orderHash,
|
||||
LibFillResults.FillResults memory fillResults)
|
||||
internal;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,17 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "../LibOrder.sol";
|
||||
import "../libs/LibOrder.sol";
|
||||
|
||||
contract MSettlement {
|
||||
|
||||
/// @dev Settles an order by transfering assets between counterparties.
|
||||
/// @param order Order struct containing order specifications.
|
||||
/// @param takerAddress Address selling takerAsset and buying makerAsset.
|
||||
/// @param takerAssetFilledAmount The amount of takerAsset that will be transfered to the order's maker.
|
||||
/// @return Amount filled by maker and fees paid by maker/taker.
|
||||
function settleOrder(
|
||||
LibOrder.Order memory order,
|
||||
address takerAddress,
|
||||
@@ -33,5 +37,5 @@ contract MSettlement {
|
||||
uint256 makerFeePaid,
|
||||
uint256 takerFeePaid
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,24 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
contract MSignatureValidator {
|
||||
import "../interfaces/ISignatureValidator.sol";
|
||||
|
||||
contract MSignatureValidator is
|
||||
ISignatureValidator
|
||||
{
|
||||
// Allowed signature types.
|
||||
enum SignatureType {
|
||||
Illegal, // Default value
|
||||
Invalid,
|
||||
Caller,
|
||||
Ecrecover,
|
||||
EIP712,
|
||||
Trezor,
|
||||
Contract,
|
||||
PreSigned
|
||||
}
|
||||
|
||||
/// @dev Verifies that a signature is valid.
|
||||
/// @param hash Message hash that is signed.
|
||||
|
||||
@@ -15,24 +15,13 @@
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "./MSignatureValidator.sol";
|
||||
import "../interfaces/ITransactions.sol";
|
||||
|
||||
contract MTransactions is MSignatureValidator {
|
||||
|
||||
/// @dev Executes an exchange method call in the context of signer.
|
||||
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.
|
||||
/// @param signer Address of transaction signer.
|
||||
/// @param data AbiV2 encoded calldata.
|
||||
/// @param signature Proof of signer transaction by signer.
|
||||
function executeTransaction(
|
||||
uint256 salt,
|
||||
address signer,
|
||||
bytes data,
|
||||
bytes signature)
|
||||
external;
|
||||
contract MTransactions is
|
||||
ITransactions
|
||||
{
|
||||
|
||||
/// @dev The current function will be called in the context of this address (either 0x transaction signer or `msg.sender`).
|
||||
/// If calling a fill function, this address will represent the taker.
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../Mintable/Mintable.sol";
|
||||
import "../../utils/Ownable/Ownable.sol";
|
||||
@@ -26,7 +27,7 @@ contract DummyERC20Token is Mintable, Ownable {
|
||||
string public symbol;
|
||||
uint256 public decimals;
|
||||
|
||||
function DummyERC20Token(
|
||||
constructor (
|
||||
string _name,
|
||||
string _symbol,
|
||||
uint256 _decimals,
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../tokens/ERC721Token/ERC721Token.sol";
|
||||
import "../../utils/Ownable/Ownable.sol";
|
||||
|
||||
@@ -30,7 +32,7 @@ contract DummyERC721Token is
|
||||
* @param name of token
|
||||
* @param symbol of token
|
||||
*/
|
||||
function DummyERC721Token(
|
||||
constructor (
|
||||
string name,
|
||||
string symbol)
|
||||
public
|
||||
@@ -47,7 +49,10 @@ contract DummyERC721Token is
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
require(!exists(tokenId));
|
||||
require(
|
||||
!exists(tokenId),
|
||||
"Token with tokenId already exists."
|
||||
);
|
||||
_mint(to, tokenId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../tokens/UnlimitedAllowanceToken/UnlimitedAllowanceToken.sol";
|
||||
import "../../utils/SafeMath/SafeMath.sol";
|
||||
@@ -29,7 +30,10 @@ contract Mintable is UnlimitedAllowanceToken, SafeMath {
|
||||
function mint(uint256 _value)
|
||||
public
|
||||
{
|
||||
require(_value <= 100000000000000000000);
|
||||
require(
|
||||
_value <= 100000000000000000000,
|
||||
"Minting more than 100000000000000000000 is not allowed."
|
||||
);
|
||||
balances[msg.sender] = safeAdd(_value, balances[msg.sender]);
|
||||
totalSupply = safeAdd(totalSupply, _value);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../protocol/Exchange/MixinAssetProxyDispatcher.sol";
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
|
||||
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.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../utils/LibBytes/LibBytes.sol";
|
||||
|
||||
contract TestLibBytes is
|
||||
LibBytes
|
||||
{
|
||||
|
||||
/// @dev Tests equality of two byte arrays.
|
||||
/// @param lhs First byte array to compare.
|
||||
/// @param rhs Second byte array to compare.
|
||||
/// @return True if arrays are the same. False otherwise.
|
||||
function publicAreBytesEqual(bytes memory lhs, bytes memory rhs)
|
||||
public
|
||||
pure
|
||||
returns (bool equal)
|
||||
{
|
||||
equal = areBytesEqual(lhs, rhs);
|
||||
return equal;
|
||||
}
|
||||
|
||||
/// @dev Reads an address from a position in a byte array.
|
||||
/// @param b Byte array containing an address.
|
||||
/// @param index Index in byte array of address.
|
||||
/// @return address from byte array.
|
||||
function publicReadAddress(
|
||||
bytes memory b,
|
||||
uint256 index)
|
||||
public
|
||||
pure
|
||||
returns (address result)
|
||||
{
|
||||
result = readAddress(b, index);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @dev Writes an address into a specific position in a byte array.
|
||||
/// @param b Byte array to insert address into.
|
||||
/// @param index Index in byte array of address.
|
||||
/// @param input Address to put into byte array.
|
||||
function publicWriteAddress(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
address input)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
writeAddress(b, index, input);
|
||||
return b;
|
||||
}
|
||||
|
||||
/// @dev Reads a bytes32 value from a position in a byte array.
|
||||
/// @param b Byte array containing a bytes32 value.
|
||||
/// @param index Index in byte array of bytes32 value.
|
||||
/// @return bytes32 value from byte array.
|
||||
function publicReadBytes32(
|
||||
bytes memory b,
|
||||
uint256 index)
|
||||
public
|
||||
pure
|
||||
returns (bytes32 result)
|
||||
{
|
||||
result = readBytes32(b, index);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @dev Writes a bytes32 into a specific position in a byte array.
|
||||
/// @param b Byte array to insert <input> into.
|
||||
/// @param index Index in byte array of <input>.
|
||||
/// @param input bytes32 to put into byte array.
|
||||
function publicWriteBytes32(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
bytes32 input)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
writeBytes32(b, index, input);
|
||||
return b;
|
||||
}
|
||||
|
||||
/// @dev Reads a uint256 value from a position in a byte array.
|
||||
/// @param b Byte array containing a uint256 value.
|
||||
/// @param index Index in byte array of uint256 value.
|
||||
/// @return uint256 value from byte array.
|
||||
function publicReadUint256(
|
||||
bytes memory b,
|
||||
uint256 index)
|
||||
public
|
||||
pure
|
||||
returns (uint256 result)
|
||||
{
|
||||
result = readUint256(b, index);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @dev Writes a uint256 into a specific position in a byte array.
|
||||
/// @param b Byte array to insert <input> into.
|
||||
/// @param index Index in byte array of <input>.
|
||||
/// @param input uint256 to put into byte array.
|
||||
function publicWriteUint256(
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
uint256 input)
|
||||
public
|
||||
pure
|
||||
returns (bytes memory)
|
||||
{
|
||||
writeUint256(b, index, input);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../protocol/Exchange/LibMath.sol";
|
||||
import "../../protocol/Exchange/LibOrder.sol";
|
||||
import "../../protocol/Exchange/LibFillResults.sol";
|
||||
import "../../protocol/Exchange/libs/LibMath.sol";
|
||||
import "../../protocol/Exchange/libs/LibOrder.sol";
|
||||
import "../../protocol/Exchange/libs/LibFillResults.sol";
|
||||
|
||||
contract TestLibs is
|
||||
LibMath,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "../../protocol/Exchange/MixinSignatureValidator.sol";
|
||||
|
||||
@@ -16,17 +16,34 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./IERC20Token.sol";
|
||||
|
||||
contract ERC20Token is IERC20Token {
|
||||
|
||||
string constant INSUFFICIENT_BALANCE = "Insufficient balance to complete transfer.";
|
||||
string constant INSUFFICIENT_ALLOWANCE = "Insufficient allowance to complete transfer.";
|
||||
string constant OVERFLOW = "Transfer would result in an overflow.";
|
||||
|
||||
mapping (address => uint256) balances;
|
||||
mapping (address => mapping (address => uint256)) allowed;
|
||||
|
||||
uint256 public totalSupply;
|
||||
|
||||
function transfer(address _to, uint256 _value)
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
require(balances[msg.sender] >= _value && balances[_to] + _value >= balances[_to]);
|
||||
require(
|
||||
balances[msg.sender] >= _value,
|
||||
INSUFFICIENT_BALANCE
|
||||
);
|
||||
require(
|
||||
balances[_to] + _value >= balances[_to],
|
||||
OVERFLOW
|
||||
);
|
||||
balances[msg.sender] -= _value;
|
||||
balances[_to] += _value;
|
||||
emit Transfer(msg.sender, _to, _value);
|
||||
@@ -37,7 +54,18 @@ contract ERC20Token is IERC20Token {
|
||||
public
|
||||
returns (bool)
|
||||
{
|
||||
require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value >= balances[_to]);
|
||||
require(
|
||||
balances[_from] >= _value,
|
||||
INSUFFICIENT_BALANCE
|
||||
);
|
||||
require(
|
||||
allowed[_from][msg.sender] >= _value,
|
||||
INSUFFICIENT_ALLOWANCE
|
||||
);
|
||||
require(
|
||||
balances[_to] + _value >= balances[_to],
|
||||
OVERFLOW
|
||||
);
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
allowed[_from][msg.sender] -= _value;
|
||||
@@ -68,8 +96,5 @@ contract ERC20Token is IERC20Token {
|
||||
{
|
||||
return allowed[_owner][_spender];
|
||||
}
|
||||
|
||||
mapping (address => uint256) balances;
|
||||
mapping (address => mapping (address => uint256)) allowed;
|
||||
uint256 public totalSupply;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract IERC20Token {
|
||||
|
||||
/// @notice send `_value` token to `_to` from `msg.sender`
|
||||
/// @notice send `value` token to `to` from `msg.sender`
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return Whether the transfer was successful or not
|
||||
@@ -28,7 +29,7 @@ contract IERC20Token {
|
||||
public
|
||||
returns (bool);
|
||||
|
||||
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
|
||||
/// @notice send `value` token to `to` from `from` on the condition it is approved by `from`
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
@@ -61,10 +62,12 @@ contract IERC20Token {
|
||||
event Transfer(
|
||||
address indexed _from,
|
||||
address indexed _to,
|
||||
uint256 _value);
|
||||
uint256 _value
|
||||
);
|
||||
|
||||
event Approval(
|
||||
address indexed _owner,
|
||||
address indexed _spender,
|
||||
uint256 _value);
|
||||
uint256 _value
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ 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;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
import "./IERC721Token.sol";
|
||||
import "./IERC721Receiver.sol";
|
||||
|
||||
@@ -23,7 +23,7 @@ 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;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
/**
|
||||
* @title ERC721 token receiver interface
|
||||
|
||||
@@ -23,7 +23,7 @@ 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;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
/**
|
||||
* @title ERC721 Non-Fungible Token Standard basic interface
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.18;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import { ERC20Token } from "../ERC20Token/ERC20Token.sol";
|
||||
import "../ERC20Token/ERC20Token.sol";
|
||||
|
||||
contract UnlimitedAllowanceToken is ERC20Token {
|
||||
|
||||
@@ -34,7 +35,18 @@ contract UnlimitedAllowanceToken is ERC20Token {
|
||||
returns (bool)
|
||||
{
|
||||
uint256 allowance = allowed[_from][msg.sender];
|
||||
require(balances[_from] >= _value && allowance >= _value && balances[_to] + _value >= balances[_to]);
|
||||
require(
|
||||
balances[_from] >= _value,
|
||||
INSUFFICIENT_BALANCE
|
||||
);
|
||||
require(
|
||||
allowance >= _value,
|
||||
INSUFFICIENT_ALLOWANCE
|
||||
);
|
||||
require(
|
||||
balances[_to] + _value >= balances[_to],
|
||||
OVERFLOW
|
||||
);
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
if (allowance < MAX_UINT) {
|
||||
|
||||
@@ -16,16 +16,21 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
|
||||
contract LibBytes {
|
||||
|
||||
// Revert reasons
|
||||
string constant GTE_20_LENGTH_REQUIRED = "Length must be greater than or equal to 20.";
|
||||
string constant GTE_32_LENGTH_REQUIRED = "Length must be greater than or equal to 32.";
|
||||
|
||||
/// @dev Tests equality of two byte arrays.
|
||||
/// @param lhs First byte array to compare.
|
||||
/// @param rhs Second byte array to compare.
|
||||
/// @return True if arrays are the same. False otherwise.
|
||||
function areBytesEqual(bytes memory lhs, bytes memory rhs)
|
||||
public pure
|
||||
internal
|
||||
pure
|
||||
returns (bool equal)
|
||||
{
|
||||
assembly {
|
||||
@@ -58,10 +63,14 @@ contract LibBytes {
|
||||
function readAddress(
|
||||
bytes memory b,
|
||||
uint256 index)
|
||||
public pure
|
||||
internal
|
||||
pure
|
||||
returns (address result)
|
||||
{
|
||||
require(b.length >= index + 20); // 20 is length of address
|
||||
require(
|
||||
b.length >= index + 20, // 20 is length of address
|
||||
GTE_20_LENGTH_REQUIRED
|
||||
);
|
||||
|
||||
// Add offset to index:
|
||||
// 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
|
||||
@@ -86,9 +95,13 @@ contract LibBytes {
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
address input)
|
||||
public pure
|
||||
internal
|
||||
pure
|
||||
{
|
||||
require(b.length >= index + 20); // 20 is length of address
|
||||
require(
|
||||
b.length >= index + 20, // 20 is length of address
|
||||
GTE_20_LENGTH_REQUIRED
|
||||
);
|
||||
|
||||
// Add offset to index:
|
||||
// 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
|
||||
@@ -119,10 +132,14 @@ contract LibBytes {
|
||||
function readBytes32(
|
||||
bytes memory b,
|
||||
uint256 index)
|
||||
public pure
|
||||
internal
|
||||
pure
|
||||
returns (bytes32 result)
|
||||
{
|
||||
require(b.length >= index + 32);
|
||||
require(
|
||||
b.length >= index + 32,
|
||||
GTE_32_LENGTH_REQUIRED
|
||||
);
|
||||
|
||||
// Arrays are prefixed by a 256 bit length parameter
|
||||
index += 32;
|
||||
@@ -142,9 +159,13 @@ contract LibBytes {
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
bytes32 input)
|
||||
public pure
|
||||
internal
|
||||
pure
|
||||
{
|
||||
require(b.length >= index + 32);
|
||||
require(
|
||||
b.length >= index + 32,
|
||||
GTE_32_LENGTH_REQUIRED
|
||||
);
|
||||
|
||||
// Arrays are prefixed by a 256 bit length parameter
|
||||
index += 32;
|
||||
@@ -162,7 +183,8 @@ contract LibBytes {
|
||||
function readUint256(
|
||||
bytes memory b,
|
||||
uint256 index)
|
||||
public pure
|
||||
internal
|
||||
pure
|
||||
returns (uint256 result)
|
||||
{
|
||||
return uint256(readBytes32(b, index));
|
||||
@@ -176,7 +198,8 @@ contract LibBytes {
|
||||
bytes memory b,
|
||||
uint256 index,
|
||||
uint256 input)
|
||||
public pure
|
||||
internal
|
||||
pure
|
||||
{
|
||||
writeBytes32(b, index, bytes32(input));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/*
|
||||
* Ownable
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/*
|
||||
* Ownable
|
||||
@@ -7,19 +8,22 @@ pragma solidity ^0.4.21;
|
||||
* Provides onlyOwner modifier, which prevents function from running if it is called by anyone other than the owner.
|
||||
*/
|
||||
|
||||
import "../Ownable/IOwnable.sol";
|
||||
import "./IOwnable.sol";
|
||||
|
||||
contract Ownable is IOwnable {
|
||||
address public owner;
|
||||
|
||||
function Ownable()
|
||||
constructor ()
|
||||
public
|
||||
{
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == owner);
|
||||
require(
|
||||
msg.sender == owner,
|
||||
"Only contract owner is allowed to call this method."
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
pragma solidity ^0.4.21;
|
||||
pragma solidity ^0.4.23;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
contract SafeMath {
|
||||
function safeMul(uint a, uint b)
|
||||
|
||||
@@ -99,7 +99,7 @@ export enum ContractName {
|
||||
ERC20Proxy = 'ERC20Proxy',
|
||||
ERC721Proxy = 'ERC721Proxy',
|
||||
DummyERC721Token = 'DummyERC721Token',
|
||||
LibBytes = 'LibBytes',
|
||||
TestLibBytes = 'TestLibBytes',
|
||||
Authorizable = 'Authorizable',
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
|
||||
import * as chai from 'chai';
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import { AuthorizableContract } from '../../src/contract_wrappers/generated/authorizable';
|
||||
import { MixinAuthorizableContract } from '../../src/contract_wrappers/generated/mixin_authorizable';
|
||||
import { constants } from '../../src/utils/constants';
|
||||
import { ContractName } from '../../src/utils/types';
|
||||
import { chaiSetup } from '../utils/chai_setup';
|
||||
@@ -18,13 +18,13 @@ describe('Authorizable', () => {
|
||||
let owner: string;
|
||||
let notOwner: string;
|
||||
let address: string;
|
||||
let authorizable: AuthorizableContract;
|
||||
let authorizable: MixinAuthorizableContract;
|
||||
before(async () => {
|
||||
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||
owner = address = accounts[0];
|
||||
notOwner = accounts[1];
|
||||
const authorizableInstance = await deployer.deployAsync(ContractName.Authorizable);
|
||||
authorizable = new AuthorizableContract(authorizableInstance.abi, authorizableInstance.address, provider);
|
||||
authorizable = new MixinAuthorizableContract(authorizableInstance.abi, authorizableInstance.address, provider);
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as chai from 'chai';
|
||||
import ethUtil = require('ethereumjs-util');
|
||||
import * as Web3 from 'web3';
|
||||
|
||||
import { LibBytesContract } from '../../src/contract_wrappers/generated/lib_bytes';
|
||||
import { TestLibBytesContract } from '../../src/contract_wrappers/generated/test_lib_bytes';
|
||||
import { constants } from '../../src/utils/constants';
|
||||
import { AssetProxyId, ContractName } from '../../src/utils/types';
|
||||
import { chaiSetup } from '../utils/chai_setup';
|
||||
@@ -20,7 +20,7 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
describe('LibBytes', () => {
|
||||
let owner: string;
|
||||
let libBytes: LibBytesContract;
|
||||
let libBytes: TestLibBytesContract;
|
||||
const byteArrayShorterThan32Bytes = '0x012345';
|
||||
const byteArrayLongerThan32Bytes =
|
||||
'0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
||||
@@ -38,8 +38,8 @@ describe('LibBytes', () => {
|
||||
owner = accounts[0];
|
||||
testAddress = accounts[1];
|
||||
// Deploy LibBytes
|
||||
const libBytesInstance = await deployer.deployAsync(ContractName.LibBytes);
|
||||
libBytes = new LibBytesContract(libBytesInstance.abi, libBytesInstance.address, provider);
|
||||
const libBytesInstance = await deployer.deployAsync(ContractName.TestLibBytes);
|
||||
libBytes = new TestLibBytesContract(libBytesInstance.abi, libBytesInstance.address, provider);
|
||||
// Verify lengths of test data
|
||||
const byteArrayShorterThan32BytesLength = ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength;
|
||||
expect(byteArrayShorterThan32BytesLength).to.be.lessThan(32);
|
||||
@@ -57,7 +57,7 @@ describe('LibBytes', () => {
|
||||
|
||||
describe('areBytesEqual', () => {
|
||||
it('should return true if byte arrays are equal (both arrays < 32 bytes)', async () => {
|
||||
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
|
||||
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
|
||||
byteArrayShorterThan32Bytes,
|
||||
byteArrayShorterThan32Bytes,
|
||||
);
|
||||
@@ -65,7 +65,7 @@ describe('LibBytes', () => {
|
||||
});
|
||||
|
||||
it('should return true if byte arrays are equal (both arrays > 32 bytes)', async () => {
|
||||
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
|
||||
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
|
||||
byteArrayLongerThan32Bytes,
|
||||
byteArrayLongerThan32Bytes,
|
||||
);
|
||||
@@ -73,7 +73,7 @@ describe('LibBytes', () => {
|
||||
});
|
||||
|
||||
it('should return false if byte arrays are not equal (first array < 32 bytes, second array > 32 bytes)', async () => {
|
||||
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
|
||||
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
|
||||
byteArrayShorterThan32Bytes,
|
||||
byteArrayLongerThan32Bytes,
|
||||
);
|
||||
@@ -81,7 +81,7 @@ describe('LibBytes', () => {
|
||||
});
|
||||
|
||||
it('should return false if byte arrays are not equal (first array > 32 bytes, second array < 32 bytes)', async () => {
|
||||
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
|
||||
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
|
||||
byteArrayLongerThan32Bytes,
|
||||
byteArrayShorterThan32Bytes,
|
||||
);
|
||||
@@ -89,7 +89,7 @@ describe('LibBytes', () => {
|
||||
});
|
||||
|
||||
it('should return false if byte arrays are not equal (same length, but a byte in first word differs)', async () => {
|
||||
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
|
||||
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
|
||||
byteArrayLongerThan32BytesFirstBytesSwapped,
|
||||
byteArrayLongerThan32Bytes,
|
||||
);
|
||||
@@ -97,7 +97,7 @@ describe('LibBytes', () => {
|
||||
});
|
||||
|
||||
it('should return false if byte arrays are not equal (same length, but a byte in last word differs)', async () => {
|
||||
const areBytesEqual = await libBytes.areBytesEqual.callAsync(
|
||||
const areBytesEqual = await libBytes.publicAreBytesEqual.callAsync(
|
||||
byteArrayLongerThan32BytesLastBytesSwapped,
|
||||
byteArrayLongerThan32Bytes,
|
||||
);
|
||||
@@ -109,7 +109,7 @@ describe('LibBytes', () => {
|
||||
it('should successfully read address when the address takes up the whole array)', async () => {
|
||||
const byteArray = ethUtil.addHexPrefix(testAddress);
|
||||
const testAddressOffset = new BigNumber(0);
|
||||
const address = await libBytes.readAddress.callAsync(byteArray, testAddressOffset);
|
||||
const address = await libBytes.publicReadAddress.callAsync(byteArray, testAddressOffset);
|
||||
return expect(address).to.be.equal(testAddress);
|
||||
});
|
||||
|
||||
@@ -119,20 +119,24 @@ describe('LibBytes', () => {
|
||||
const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, addressByteArrayBuffer]);
|
||||
const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
|
||||
const testAddressOffset = new BigNumber(prefixByteArrayBuffer.byteLength);
|
||||
const address = await libBytes.readAddress.callAsync(combinedByteArray, testAddressOffset);
|
||||
const address = await libBytes.publicReadAddress.callAsync(combinedByteArray, testAddressOffset);
|
||||
return expect(address).to.be.equal(testAddress);
|
||||
});
|
||||
|
||||
it('should fail if the byte array is too short to hold an address)', async () => {
|
||||
const shortByteArray = '0xabcdef';
|
||||
const offset = new BigNumber(0);
|
||||
return expect(libBytes.readAddress.callAsync(shortByteArray, offset)).to.be.rejectedWith(constants.REVERT);
|
||||
return expect(libBytes.publicReadAddress.callAsync(shortByteArray, offset)).to.be.rejectedWith(
|
||||
constants.REVERT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should fail if the length between the offset and end of the byte array is too short to hold an address)', async () => {
|
||||
const byteArray = ethUtil.addHexPrefix(testAddress);
|
||||
const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength);
|
||||
return expect(libBytes.readAddress.callAsync(byteArray, badOffset)).to.be.rejectedWith(constants.REVERT);
|
||||
return expect(libBytes.publicReadAddress.callAsync(byteArray, badOffset)).to.be.rejectedWith(
|
||||
constants.REVERT,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -150,7 +154,7 @@ describe('LibBytes', () => {
|
||||
describe('readBytes32', () => {
|
||||
it('should successfully read bytes32 when the bytes32 takes up the whole array)', async () => {
|
||||
const testBytes32Offset = new BigNumber(0);
|
||||
const bytes32 = await libBytes.readBytes32.callAsync(testBytes32, testBytes32Offset);
|
||||
const bytes32 = await libBytes.publicReadBytes32.callAsync(testBytes32, testBytes32Offset);
|
||||
return expect(bytes32).to.be.equal(testBytes32);
|
||||
});
|
||||
|
||||
@@ -160,20 +164,22 @@ describe('LibBytes', () => {
|
||||
const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, bytes32ByteArrayBuffer]);
|
||||
const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
|
||||
const testAddressOffset = new BigNumber(prefixByteArrayBuffer.byteLength);
|
||||
const bytes32 = await libBytes.readBytes32.callAsync(combinedByteArray, testAddressOffset);
|
||||
const bytes32 = await libBytes.publicReadBytes32.callAsync(combinedByteArray, testAddressOffset);
|
||||
return expect(bytes32).to.be.equal(testBytes32);
|
||||
});
|
||||
|
||||
it('should fail if the byte array is too short to hold a bytes32)', async () => {
|
||||
const offset = new BigNumber(0);
|
||||
return expect(libBytes.readBytes32.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith(
|
||||
return expect(libBytes.publicReadBytes32.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith(
|
||||
constants.REVERT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should fail if the length between the offset and end of the byte array is too short to hold a bytes32)', async () => {
|
||||
const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength);
|
||||
return expect(libBytes.readBytes32.callAsync(testBytes32, badOffset)).to.be.rejectedWith(constants.REVERT);
|
||||
return expect(libBytes.publicReadBytes32.callAsync(testBytes32, badOffset)).to.be.rejectedWith(
|
||||
constants.REVERT,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -194,7 +200,7 @@ describe('LibBytes', () => {
|
||||
const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256);
|
||||
const byteArray = ethUtil.bufferToHex(testUint256AsBuffer);
|
||||
const testUint256Offset = new BigNumber(0);
|
||||
const uint256 = await libBytes.readUint256.callAsync(byteArray, testUint256Offset);
|
||||
const uint256 = await libBytes.publicReadUint256.callAsync(byteArray, testUint256Offset);
|
||||
return expect(uint256).to.bignumber.equal(testUint256);
|
||||
});
|
||||
|
||||
@@ -205,13 +211,13 @@ describe('LibBytes', () => {
|
||||
const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, testUint256AsBuffer]);
|
||||
const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
|
||||
const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength);
|
||||
const uint256 = await libBytes.readUint256.callAsync(combinedByteArray, testUint256Offset);
|
||||
const uint256 = await libBytes.publicReadUint256.callAsync(combinedByteArray, testUint256Offset);
|
||||
return expect(uint256).to.bignumber.equal(testUint256);
|
||||
});
|
||||
|
||||
it('should fail if the byte array is too short to hold a uint256)', async () => {
|
||||
const offset = new BigNumber(0);
|
||||
return expect(libBytes.readUint256.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith(
|
||||
return expect(libBytes.publicReadUint256.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith(
|
||||
constants.REVERT,
|
||||
);
|
||||
});
|
||||
@@ -221,7 +227,9 @@ describe('LibBytes', () => {
|
||||
const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256);
|
||||
const byteArray = ethUtil.bufferToHex(testUint256AsBuffer);
|
||||
const badOffset = new BigNumber(testUint256AsBuffer.byteLength);
|
||||
return expect(libBytes.readUint256.callAsync(byteArray, badOffset)).to.be.rejectedWith(constants.REVERT);
|
||||
return expect(libBytes.publicReadUint256.callAsync(byteArray, badOffset)).to.be.rejectedWith(
|
||||
constants.REVERT,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user