aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts
diff options
context:
space:
mode:
authorGreg Hysen <hysz@users.noreply.github.com>2018-06-09 02:58:23 +0800
committerGitHub <noreply@github.com>2018-06-09 02:58:23 +0800
commit817c332d11835f02726f0609374d1c25c9ab39b5 (patch)
treed84c9a96465b5e862629be3dd04325dcccdbc780 /packages/contracts
parentadd9a9db9ba4294cf12489bf589c527b0921ed1e (diff)
parent05fbc8e6b061e5cef5bb8b8078176f9b375c2ec5 (diff)
downloaddexon-sol-tools-817c332d11835f02726f0609374d1c25c9ab39b5.tar.gz
dexon-sol-tools-817c332d11835f02726f0609374d1c25c9ab39b5.tar.zst
dexon-sol-tools-817c332d11835f02726f0609374d1c25c9ab39b5.zip
Merge pull request #627 from 0xProject/feature/contracts/erc721SafeTransferFrom
On-Chain AssetData Decoding Lib + safeTransferFrom for ERC721 + Memcpy
Diffstat (limited to 'packages/contracts')
-rw-r--r--packages/contracts/compiler.json3
-rw-r--r--packages/contracts/package.json2
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol48
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol77
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol14
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol8
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol4
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol4
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol4
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol10
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol10
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol59
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol3
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol3
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol27
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol4
-rw-r--r--packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol3
-rw-r--r--packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol63
-rw-r--r--packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol3
-rw-r--r--packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol77
-rw-r--r--packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol4
-rw-r--r--packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol52
-rw-r--r--packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol56
-rw-r--r--packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol97
-rw-r--r--packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol140
-rw-r--r--packages/contracts/src/utils/artifacts.ts6
-rw-r--r--packages/contracts/src/utils/constants.ts10
-rw-r--r--packages/contracts/src/utils/match_order_tester.ts24
-rw-r--r--packages/contracts/src/utils/types.ts3
-rw-r--r--packages/contracts/test/asset_proxy/decoder.ts103
-rw-r--r--packages/contracts/test/asset_proxy/proxies.ts234
-rw-r--r--packages/contracts/test/exchange/core.ts38
-rw-r--r--packages/contracts/test/exchange/dispatcher.ts8
-rw-r--r--packages/contracts/test/exchange/libs.ts4
-rw-r--r--packages/contracts/test/exchange/match_orders.ts132
-rw-r--r--packages/contracts/test/exchange/signature_validator.ts4
-rw-r--r--packages/contracts/test/exchange/transactions.ts10
-rw-r--r--packages/contracts/test/exchange/wrapper.ts26
-rw-r--r--packages/contracts/test/libraries/lib_bytes.ts224
-rw-r--r--packages/contracts/test/libraries/lib_mem.ts190
40 files changed, 1429 insertions, 362 deletions
diff --git a/packages/contracts/compiler.json b/packages/contracts/compiler.json
index 48ba4ffcd..6ef8e6a95 100644
--- a/packages/contracts/compiler.json
+++ b/packages/contracts/compiler.json
@@ -21,6 +21,7 @@
"contracts": [
"AssetProxyOwner",
"DummyERC20Token",
+ "DummyERC721Receiver",
"DummyERC721Token",
"ERC20Proxy",
"ERC721Proxy",
@@ -28,8 +29,10 @@
"MixinAuthorizable",
"MultiSigWallet",
"MultiSigWalletWithTimeLock",
+ "TestAssetDataDecoders",
"TestAssetProxyDispatcher",
"TestLibBytes",
+ "TestLibMem",
"TestLibs",
"TestSignatureValidator",
"TokenRegistry",
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 99c507197..b533a22ce 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -30,7 +30,7 @@
"test:circleci": "yarn test"
},
"config": {
- "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyDispatcher|TestLibBytes|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json"
+ "abis": "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetDataDecoders|TestAssetProxyDispatcher|TestLibBytes|TestLibMem|TestLibs|TestSignatureValidator|TokenRegistry|Whitelist|WETH9|ZRXToken).json"
},
"repository": {
"type": "git",
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
index 2c321e134..dd25bf41a 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
@@ -34,34 +34,30 @@ contract ERC20Proxy is
uint8 constant PROXY_ID = 1;
/// @dev Internal version of `transferFrom`.
- /// @param assetMetadata Encoded byte array.
+ /// @param assetData Encoded byte array.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
function transferFromInternal(
- bytes memory assetMetadata,
+ bytes memory assetData,
address from,
address to,
uint256 amount
)
internal
{
- // Data must be intended for this proxy.
- uint256 length = assetMetadata.length;
+ // Decode asset data.
+ (
+ uint8 proxyId,
+ address token
+ ) = decodeERC20AssetData(assetData);
+ // Data must be intended for this proxy.
require(
- length == 21,
- LENGTH_21_REQUIRED
- );
- // TODO: Is this too inflexible in the future?
- require(
- uint8(assetMetadata[length - 1]) == PROXY_ID,
+ proxyId == PROXY_ID,
ASSET_PROXY_ID_MISMATCH
);
- // Decode metadata.
- address token = readAddress(assetMetadata, 0);
-
// Transfer tokens.
bool success = IERC20Token(token).transferFrom(from, to, amount);
require(
@@ -79,4 +75,30 @@ contract ERC20Proxy is
{
return PROXY_ID;
}
+
+ /// @dev Decodes ERC20 Asset data.
+ /// @param assetData Encoded byte array.
+ /// @return proxyId Intended ERC20 proxy id.
+ /// @return token ERC20 token address.
+ function decodeERC20AssetData(bytes memory assetData)
+ internal
+ pure
+ returns (
+ uint8 proxyId,
+ address token
+ )
+ {
+ // Validate encoded data length
+ uint256 length = assetData.length;
+ require(
+ length == 21,
+ LENGTH_21_REQUIRED
+ );
+
+ // Decode data
+ token = readAddress(assetData, 0);
+ proxyId = uint8(assetData[length - 1]);
+
+ return (proxyId, token);
+ }
}
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
index 07e01c774..25136133d 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
@@ -34,29 +34,30 @@ contract ERC721Proxy is
uint8 constant PROXY_ID = 2;
/// @dev Internal version of `transferFrom`.
- /// @param assetMetadata Encoded byte array.
+ /// @param assetData Encoded byte array.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
function transferFromInternal(
- bytes memory assetMetadata,
+ bytes memory assetData,
address from,
address to,
uint256 amount
)
internal
{
- // Data must be intended for this proxy.
- uint256 length = assetMetadata.length;
+ // Decode asset data.
+ (
+ uint8 proxyId,
+ address token,
+ uint256 tokenId,
+ bytes memory receiverData
+ ) = decodeERC721AssetData(assetData);
- require(
- length == 53,
- LENGTH_53_REQUIRED
- );
- // TODO: Is this too inflexible in the future?
+ // Data must be intended for this proxy.
require(
- uint8(assetMetadata[length - 1]) == PROXY_ID,
+ proxyId == PROXY_ID,
ASSET_PROXY_ID_MISMATCH
);
@@ -66,15 +67,13 @@ contract ERC721Proxy is
INVALID_AMOUNT
);
- // Decode metadata
- address token = readAddress(assetMetadata, 0);
- uint256 tokenId = readUint256(assetMetadata, 20);
-
- // Transfer token.
- // Either succeeds or throws.
- // @TODO: Call safeTransferFrom if there is additional
- // data stored in `assetMetadata`.
- ERC721Token(token).transferFrom(from, to, tokenId);
+ // Transfer token. Saves gas by calling safeTransferFrom only
+ // when there is receiverData present. Either succeeds or throws.
+ if(receiverData.length > 0) {
+ ERC721Token(token).safeTransferFrom(from, to, tokenId, receiverData);
+ } else {
+ ERC721Token(token).transferFrom(from, to, tokenId);
+ }
}
/// @dev Gets the proxy id associated with the proxy address.
@@ -86,4 +85,44 @@ contract ERC721Proxy is
{
return PROXY_ID;
}
+
+ /// @dev Decodes ERC721 Asset data.
+ /// @param assetData Encoded byte array.
+ /// @return proxyId Intended ERC721 proxy id.
+ /// @return token ERC721 token address.
+ /// @return tokenId ERC721 token id.
+ /// @return receiverData Additional data with no specific format, which
+ /// is passed to the receiving contract's onERC721Received.
+ function decodeERC721AssetData(bytes memory assetData)
+ internal
+ pure
+ returns (
+ uint8 proxyId,
+ address token,
+ uint256 tokenId,
+ bytes memory receiverData
+ )
+ {
+ // Validate encoded data length
+ uint256 length = assetData.length;
+ require(
+ length >= 53,
+ LENGTH_AT_LEAST_53_REQUIRED
+ );
+
+ // Decode asset data.
+ token = readAddress(assetData, 0);
+ tokenId = readUint256(assetData, 20);
+ if (length > 53) {
+ receiverData = readBytes(assetData, 52);
+ }
+ proxyId = uint8(assetData[length - 1]);
+
+ return (
+ proxyId,
+ token,
+ tokenId,
+ receiverData
+ );
+ }
}
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol
index 5fa33cbef..9032658e7 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinAssetProxy.sol
@@ -28,12 +28,12 @@ contract MixinAssetProxy is
{
/// @dev Transfers assets. Either succeeds or throws.
- /// @param assetMetadata Encoded byte array.
+ /// @param assetData Encoded byte array.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
function transferFrom(
- bytes assetMetadata,
+ bytes assetData,
address from,
address to,
uint256 amount
@@ -42,7 +42,7 @@ contract MixinAssetProxy is
onlyAuthorized
{
transferFromInternal(
- assetMetadata,
+ assetData,
from,
to,
amount
@@ -50,12 +50,12 @@ contract MixinAssetProxy is
}
/// @dev Makes multiple transfers of assets. Either succeeds or throws.
- /// @param assetMetadata Array of byte arrays encoded for the respective asset proxy.
+ /// @param assetData Array of byte arrays encoded for the respective asset proxy.
/// @param from Array of addresses to transfer assets from.
/// @param to Array of addresses to transfer assets to.
/// @param amounts Array of amounts of assets to transfer.
function batchTransferFrom(
- bytes[] memory assetMetadata,
+ bytes[] memory assetData,
address[] memory from,
address[] memory to,
uint256[] memory amounts
@@ -63,9 +63,9 @@ contract MixinAssetProxy is
public
onlyAuthorized
{
- for (uint256 i = 0; i < assetMetadata.length; i++) {
+ for (uint256 i = 0; i < assetData.length; i++) {
transferFromInternal(
- assetMetadata[i],
+ assetData[i],
from[i],
to[i],
amounts[i]
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol
index 7e1848889..22f43b12f 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol
@@ -26,12 +26,12 @@ contract IAssetProxy is
{
/// @dev Transfers assets. Either succeeds or throws.
- /// @param assetMetadata Byte array encoded for the respective asset proxy.
+ /// @param assetData Byte array encoded for the respective asset proxy.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
function transferFrom(
- bytes assetMetadata,
+ bytes assetData,
address from,
address to,
uint256 amount
@@ -39,12 +39,12 @@ contract IAssetProxy is
external;
/// @dev Makes multiple transfers of assets. Either succeeds or throws.
- /// @param assetMetadata Array of byte arrays encoded for the respective asset proxy.
+ /// @param assetData Array of byte arrays encoded for the respective asset proxy.
/// @param from Array of addresses to transfer assets from.
/// @param to Array of addresses to transfer assets to.
/// @param amounts Array of amounts of assets to transfer.
function batchTransferFrom(
- bytes[] memory assetMetadata,
+ bytes[] memory assetData,
address[] memory from,
address[] memory to,
uint256[] memory amounts
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol
index e0c7fc796..80180a0d9 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol
@@ -29,9 +29,9 @@ contract LibAssetProxyErrors {
/// AssetProxy errors ///
string constant ASSET_PROXY_ID_MISMATCH = "ASSET_PROXY_ID_MISMATCH"; // Proxy id in metadata does not match this proxy id.
string constant INVALID_AMOUNT = "INVALID_AMOUNT"; // Transfer amount must equal 1.
- string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Transfer failed.
+ string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Transfer failed.
/// Length validation errors ///
string constant LENGTH_21_REQUIRED = "LENGTH_21_REQUIRED"; // Byte array must have a length of 21.
- string constant LENGTH_53_REQUIRED = "LENGTH_53_REQUIRED"; // Byte array must have a length of 53.
+ string constant LENGTH_AT_LEAST_53_REQUIRED = "LENGTH_AT_LEAST_53_REQUIRED"; // Byte array must have a length of at least 53.
}
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol
index de9d65a53..a52cb56f9 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/mixins/MAssetProxy.sol
@@ -26,12 +26,12 @@ contract MAssetProxy is
{
/// @dev Internal version of `transferFrom`.
- /// @param assetMetadata Encoded byte array.
+ /// @param assetData Encoded byte array.
/// @param from Address to transfer asset from.
/// @param to Address to transfer asset to.
/// @param amount Amount of asset to transfer.
function transferFromInternal(
- bytes memory assetMetadata,
+ bytes memory assetData,
address from,
address to,
uint256 amount
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
index b7b308069..51f99bafa 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/Exchange.sol
@@ -40,11 +40,11 @@ contract Exchange is
string constant public VERSION = "2.0.1-alpha";
// Mixins are instantiated in the order they are inherited
- constructor (bytes memory _zrxProxyData)
+ constructor (bytes memory _zrxAssetData)
public
MixinExchangeCore()
MixinMatchOrders()
- MixinSettlement(_zrxProxyData)
+ MixinSettlement(_zrxAssetData)
MixinSignatureValidator()
MixinTransactions()
MixinAssetProxyDispatcher()
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
index 8f9342739..e77d81c06 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
@@ -80,12 +80,12 @@ contract MixinAssetProxyDispatcher is
}
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
- /// @param assetMetadata Byte array encoded for the respective asset proxy.
+ /// @param assetData 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,
+ bytes memory assetData,
address from,
address to,
uint256 amount
@@ -96,16 +96,16 @@ contract MixinAssetProxyDispatcher is
if (amount > 0) {
// Lookup asset proxy
- uint256 length = assetMetadata.length;
+ uint256 length = assetData.length;
require(
length > 0,
LENGTH_GREATER_THAN_0_REQUIRED
);
- uint8 assetProxyId = uint8(assetMetadata[length - 1]);
+ uint8 assetProxyId = uint8(assetData[length - 1]);
IAssetProxy assetProxy = assetProxies[assetProxyId];
// transferFrom will either succeed or throw.
- assetProxy.transferFrom(assetMetadata, from, to, amount);
+ assetProxy.transferFrom(assetData, from, to, amount);
}
}
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
index 646d3ed58..83e9dfdf4 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSettlement.sol
@@ -40,7 +40,7 @@ contract MixinSettlement is
bytes internal ZRX_PROXY_DATA;
/// @dev Gets the ZRX metadata used for fee transfers.
- function zrxProxyData()
+ function zrxAssetData()
external
view
returns (bytes memory)
@@ -48,13 +48,13 @@ contract MixinSettlement is
return ZRX_PROXY_DATA;
}
- /// TODO: _zrxProxyData should be a constant in production.
+ /// TODO: _zrxAssetData 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)
+ /// @param _zrxAssetData Byte array containing ERC20 proxy id concatenated with address of ZRX.
+ constructor (bytes memory _zrxAssetData)
public
{
- ZRX_PROXY_DATA = _zrxProxyData;
+ ZRX_PROXY_DATA = _zrxAssetData;
}
/// @dev Settles an order by transferring assets between counterparties.
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
index 0ad0710ce..e09f80bcc 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol
@@ -40,7 +40,8 @@ contract MixinWrapperFunctions is
function fillOrKillOrder(
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
- bytes memory signature)
+ bytes memory signature
+ )
public
returns (FillResults memory fillResults)
{
@@ -65,7 +66,8 @@ contract MixinWrapperFunctions is
function fillOrderNoThrow(
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
- bytes memory signature)
+ bytes memory signature
+ )
public
returns (FillResults memory fillResults)
{
@@ -91,12 +93,12 @@ contract MixinWrapperFunctions is
// | | 0x0E0 | | 8. takerFeeAmount |
// | | 0x100 | | 9. expirationTimeSeconds |
// | | 0x120 | | 10. salt |
- // | | 0x140 | | 11. Offset to makerAssetProxyMetadata (*) |
- // | | 0x160 | | 12. Offset to takerAssetProxyMetadata (*) |
- // | | 0x180 | 32 | makerAssetProxyMetadata Length |
- // | | 0x1A0 | ** | makerAssetProxyMetadata Contents |
- // | | 0x1C0 | 32 | takerAssetProxyMetadata Length |
- // | | 0x1E0 | ** | takerAssetProxyMetadata Contents |
+ // | | 0x140 | | 11. Offset to makerAssetData (*) |
+ // | | 0x160 | | 12. Offset to takerAssetData (*) |
+ // | | 0x180 | 32 | makerAssetData Length |
+ // | | 0x1A0 | ** | makerAssetData Contents |
+ // | | 0x1C0 | 32 | takerAssetData Length |
+ // | | 0x1E0 | ** | takerAssetData Contents |
// | | 0x200 | 32 | signature Length |
// | | 0x220 | ** | signature Contents |
@@ -163,43 +165,43 @@ contract MixinWrapperFunctions is
mstore(add(dataAreaEnd, 0xE0), mload(add(sourceOffset, 0xE0))) // takerFeeAmount
mstore(add(dataAreaEnd, 0x100), mload(add(sourceOffset, 0x100))) // expirationTimeSeconds
mstore(add(dataAreaEnd, 0x120), mload(add(sourceOffset, 0x120))) // salt
- mstore(add(dataAreaEnd, 0x140), mload(add(sourceOffset, 0x140))) // Offset to makerAssetProxyMetadata
- mstore(add(dataAreaEnd, 0x160), mload(add(sourceOffset, 0x160))) // Offset to takerAssetProxyMetadata
+ mstore(add(dataAreaEnd, 0x140), mload(add(sourceOffset, 0x140))) // Offset to makerAssetData
+ mstore(add(dataAreaEnd, 0x160), mload(add(sourceOffset, 0x160))) // Offset to takerAssetData
dataAreaEnd := add(dataAreaEnd, 0x180)
sourceOffset := add(sourceOffset, 0x180)
- // Write offset to <order.makerAssetProxyMetadata>
+ // Write offset to <order.makerAssetData>
mstore(add(dataAreaStart, mul(10, 0x20)), sub(dataAreaEnd, dataAreaStart))
- // Calculate length of <order.makerAssetProxyMetadata>
+ // Calculate length of <order.makerAssetData>
arrayLenBytes := mload(sourceOffset)
sourceOffset := add(sourceOffset, 0x20)
arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20)
- // Write length of <order.makerAssetProxyMetadata>
+ // Write length of <order.makerAssetData>
mstore(dataAreaEnd, arrayLenBytes)
dataAreaEnd := add(dataAreaEnd, 0x20)
- // Write contents of <order.makerAssetProxyMetadata>
+ // Write contents of <order.makerAssetData>
for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} {
mstore(dataAreaEnd, mload(sourceOffset))
dataAreaEnd := add(dataAreaEnd, 0x20)
sourceOffset := add(sourceOffset, 0x20)
}
- // Write offset to <order.takerAssetProxyMetadata>
+ // Write offset to <order.takerAssetData>
mstore(add(dataAreaStart, mul(11, 0x20)), sub(dataAreaEnd, dataAreaStart))
- // Calculate length of <order.takerAssetProxyMetadata>
+ // Calculate length of <order.takerAssetData>
arrayLenBytes := mload(sourceOffset)
sourceOffset := add(sourceOffset, 0x20)
arrayLenWords := div(add(arrayLenBytes, 0x1F), 0x20)
- // Write length of <order.takerAssetProxyMetadata>
+ // Write length of <order.takerAssetData>
mstore(dataAreaEnd, arrayLenBytes)
dataAreaEnd := add(dataAreaEnd, 0x20)
- // Write contents of <order.takerAssetProxyMetadata>
+ // Write contents of <order.takerAssetData>
for {let i := 0} lt(i, arrayLenWords) {i := add(i, 1)} {
mstore(dataAreaEnd, mload(sourceOffset))
dataAreaEnd := add(dataAreaEnd, 0x20)
@@ -264,7 +266,8 @@ contract MixinWrapperFunctions is
function batchFillOrders(
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
{
for (uint256 i = 0; i < orders.length; i++) {
@@ -283,7 +286,8 @@ contract MixinWrapperFunctions is
function batchFillOrKillOrders(
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
{
for (uint256 i = 0; i < orders.length; i++) {
@@ -303,7 +307,8 @@ contract MixinWrapperFunctions is
function batchFillOrdersNoThrow(
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
{
for (uint256 i = 0; i < orders.length; i++) {
@@ -323,7 +328,8 @@ contract MixinWrapperFunctions is
function marketSellOrders(
LibOrder.Order[] memory orders,
uint256 takerAssetFillAmount,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
returns (FillResults memory totalFillResults)
{
@@ -366,7 +372,8 @@ contract MixinWrapperFunctions is
function marketSellOrdersNoThrow(
LibOrder.Order[] memory orders,
uint256 takerAssetFillAmount,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
returns (FillResults memory totalFillResults)
{
@@ -408,7 +415,8 @@ contract MixinWrapperFunctions is
function marketBuyOrders(
LibOrder.Order[] memory orders,
uint256 makerAssetFillAmount,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
returns (FillResults memory totalFillResults)
{
@@ -459,7 +467,8 @@ contract MixinWrapperFunctions is
function marketBuyOrdersNoThrow(
LibOrder.Order[] memory orders,
uint256 makerAssetFillAmount,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
returns (FillResults memory totalFillResults)
{
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol
index 3ce5ef157..2c331dc34 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol
@@ -28,7 +28,8 @@ contract IAssetProxyDispatcher {
function registerAssetProxy(
uint8 assetProxyId,
address newAssetProxy,
- address oldAssetProxy)
+ address oldAssetProxy
+ )
external;
/// @dev Gets an asset proxy.
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol
index d973bf001..2f9a5bc7c 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ITransactions.sol
@@ -28,6 +28,7 @@ contract ITransactions {
uint256 salt,
address signer,
bytes data,
- bytes signature)
+ bytes signature
+ )
external;
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol
index 8682b394a..acd4f359c 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol
@@ -33,7 +33,8 @@ contract IWrapperFunctions is
function fillOrKillOrder(
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
- bytes memory signature)
+ bytes memory signature
+ )
public
returns (LibFillResults.FillResults memory fillResults);
@@ -46,7 +47,8 @@ contract IWrapperFunctions is
function fillOrderNoThrow(
LibOrder.Order memory order,
uint256 takerAssetFillAmount,
- bytes memory signature)
+ bytes memory signature
+ )
public
returns (LibFillResults.FillResults memory fillResults);
@@ -57,7 +59,8 @@ contract IWrapperFunctions is
function batchFillOrders(
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public;
/// @dev Synchronously executes multiple calls of fillOrKill.
@@ -67,7 +70,8 @@ contract IWrapperFunctions is
function batchFillOrKillOrders(
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public;
/// @dev Fills an order with specified parameters and ECDSA signature.
@@ -78,7 +82,8 @@ contract IWrapperFunctions is
function batchFillOrdersNoThrow(
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public;
/// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker.
@@ -89,7 +94,8 @@ contract IWrapperFunctions is
function marketSellOrders(
LibOrder.Order[] memory orders,
uint256 takerAssetFillAmount,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
returns (LibFillResults.FillResults memory totalFillResults);
@@ -102,7 +108,8 @@ contract IWrapperFunctions is
function marketSellOrdersNoThrow(
LibOrder.Order[] memory orders,
uint256 takerAssetFillAmount,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
returns (LibFillResults.FillResults memory totalFillResults);
@@ -114,7 +121,8 @@ contract IWrapperFunctions is
function marketBuyOrders(
LibOrder.Order[] memory orders,
uint256 makerAssetFillAmount,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
returns (LibFillResults.FillResults memory totalFillResults);
@@ -127,7 +135,8 @@ contract IWrapperFunctions is
function marketBuyOrdersNoThrow(
LibOrder.Order[] memory orders,
uint256 makerAssetFillAmount,
- bytes[] memory signatures)
+ bytes[] memory signatures
+ )
public
returns (LibFillResults.FillResults memory totalFillResults);
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
index 87c5f6361..82eafb529 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
@@ -33,12 +33,12 @@ contract MAssetProxyDispatcher is
);
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
- /// @param assetMetadata Byte array encoded for the respective asset proxy.
+ /// @param assetData 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,
+ bytes memory assetData,
address from,
address to,
uint256 amount
diff --git a/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol b/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol
index 0c7b18c0c..b2fe2df06 100644
--- a/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol
+++ b/packages/contracts/src/contracts/current/test/DummyERC20Token/DummyERC20Token.sol
@@ -31,7 +31,8 @@ contract DummyERC20Token is Mintable, Ownable {
string _name,
string _symbol,
uint256 _decimals,
- uint256 _totalSupply)
+ uint256 _totalSupply
+ )
public
{
name = _name;
diff --git a/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol b/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol
new file mode 100644
index 000000000..c584d0b54
--- /dev/null
+++ b/packages/contracts/src/contracts/current/test/DummyERC721Receiver/DummyERC721Receiver.sol
@@ -0,0 +1,63 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 Smart Contract Solutions, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+pragma solidity ^0.4.24;
+
+import "../../tokens/ERC721Token/IERC721Receiver.sol";
+
+contract DummyERC721Receiver is
+ IERC721Receiver
+{
+
+ event TokenReceived(
+ address from,
+ uint256 tokenId,
+ bytes data
+ );
+
+ /**
+ * @notice Handle the receipt of an NFT
+ * @dev The ERC721 smart contract calls this function on the recipient
+ * after a `safetransfer`. This function MAY throw to revert and reject the
+ * transfer. This function MUST use 50,000 gas or less. Return of other
+ * than the magic value MUST result in the transaction being reverted.
+ * Note: the contract address is always the message sender.
+ * @param _from The sending address
+ * @param _tokenId The NFT identifier which is being transfered
+ * @param _data Additional data with no specified format
+ * @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
+ */
+ function onERC721Received(
+ address _from,
+ uint256 _tokenId,
+ bytes _data
+ )
+ public
+ returns (bytes4)
+ {
+ emit TokenReceived(_from, _tokenId, _data);
+ return ERC721_RECEIVED;
+ }
+}
diff --git a/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol b/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
index 369a2950d..5503eb2f2 100644
--- a/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
+++ b/packages/contracts/src/contracts/current/test/DummyERC721Token/DummyERC721Token.sol
@@ -34,7 +34,8 @@ contract DummyERC721Token is
*/
constructor (
string name,
- string symbol)
+ string symbol
+ )
public
ERC721Token(name, symbol)
{}
diff --git a/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol b/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol
new file mode 100644
index 000000000..2c6a8fdb0
--- /dev/null
+++ b/packages/contracts/src/contracts/current/test/TestAssetDataDecoders/TestAssetDataDecoders.sol
@@ -0,0 +1,77 @@
+/*
+
+ Copyright 2018 ZeroEx Intl.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+pragma solidity ^0.4.24;
+pragma experimental ABIEncoderV2;
+
+import "../../protocol/AssetProxy/ERC20Proxy.sol";
+import "../../protocol/AssetProxy/ERC721Proxy.sol";
+
+contract TestAssetDataDecoders is
+ ERC20Proxy,
+ ERC721Proxy
+{
+
+ /// @dev Decodes ERC20 Asset data.
+ /// @param assetData Encoded byte array.
+ /// @return proxyId Intended ERC20 proxy id.
+ /// @return token ERC20 token address.
+ function publicDecodeERC20Data(bytes memory assetData)
+ public
+ pure
+ returns (
+ uint8 proxyId,
+ address token
+ )
+ {
+ (proxyId, token) = decodeERC20AssetData(assetData);
+ return (proxyId, token);
+ }
+
+ /// @dev Decodes ERC721 Asset data.
+ /// @param assetData Encoded byte array.
+ /// @return proxyId Intended ERC721 proxy id.
+ /// @return token ERC721 token address.
+ /// @return tokenId ERC721 token id.
+ /// @return receiverData Additional data with no specific format, which
+ /// is passed to the receiving contract's onERC721Received.
+ function publicDecodeERC721Data(bytes memory assetData)
+ public
+ pure
+ returns (
+ uint8 proxyId,
+ address token,
+ uint256 tokenId,
+ bytes memory receiverData
+ )
+ {
+ (
+ proxyId,
+ token,
+ tokenId,
+ receiverData
+ ) = decodeERC721AssetData(assetData);
+
+ return (
+ proxyId,
+ token,
+ tokenId,
+ receiverData
+ );
+ }
+}
diff --git a/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
index 11ca0617d..2ae69e0ef 100644
--- a/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/test/TestAssetProxyDispatcher/TestAssetProxyDispatcher.sol
@@ -23,12 +23,12 @@ import "../../protocol/Exchange/MixinAssetProxyDispatcher.sol";
contract TestAssetProxyDispatcher is MixinAssetProxyDispatcher {
function publicDispatchTransferFrom(
- bytes memory assetMetadata,
+ bytes memory assetData,
address from,
address to,
uint256 amount)
public
{
- dispatchTransferFrom(assetMetadata, from, to, amount);
+ dispatchTransferFrom(assetData, from, to, amount);
}
}
diff --git a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol
index 69554605d..22c84504c 100644
--- a/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol
+++ b/packages/contracts/src/contracts/current/test/TestLibBytes/TestLibBytes.sol
@@ -68,7 +68,8 @@ contract TestLibBytes is
/// @return address from byte array.
function publicReadAddress(
bytes memory b,
- uint256 index)
+ uint256 index
+ )
public
pure
returns (address result)
@@ -84,7 +85,8 @@ contract TestLibBytes is
function publicWriteAddress(
bytes memory b,
uint256 index,
- address input)
+ address input
+ )
public
pure
returns (bytes memory)
@@ -99,7 +101,8 @@ contract TestLibBytes is
/// @return bytes32 value from byte array.
function publicReadBytes32(
bytes memory b,
- uint256 index)
+ uint256 index
+ )
public
pure
returns (bytes32 result)
@@ -115,7 +118,8 @@ contract TestLibBytes is
function publicWriteBytes32(
bytes memory b,
uint256 index,
- bytes32 input)
+ bytes32 input
+ )
public
pure
returns (bytes memory)
@@ -130,7 +134,8 @@ contract TestLibBytes is
/// @return uint256 value from byte array.
function publicReadUint256(
bytes memory b,
- uint256 index)
+ uint256 index
+ )
public
pure
returns (uint256 result)
@@ -146,7 +151,8 @@ contract TestLibBytes is
function publicWriteUint256(
bytes memory b,
uint256 index,
- uint256 input)
+ uint256 input
+ )
public
pure
returns (bytes memory)
@@ -166,4 +172,38 @@ contract TestLibBytes is
result = readFirst4(b);
return result;
}
+
+ /// @dev Reads nested bytes from a specific position.
+ /// @param b Byte array containing nested bytes.
+ /// @param index Index of nested bytes.
+ /// @return result Nested bytes.
+ function publicReadBytes(
+ bytes memory b,
+ uint256 index
+ )
+ public
+ pure
+ returns (bytes memory result)
+ {
+ result = readBytes(b, index);
+ return result;
+ }
+
+ /// @dev Inserts bytes at 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 bytes to insert.
+ /// @return b Updated input byte array
+ function publicWriteBytes(
+ bytes memory b,
+ uint256 index,
+ bytes memory input
+ )
+ public
+ pure
+ returns (bytes memory)
+ {
+ writeBytes(b, index, input);
+ return b;
+ }
}
diff --git a/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol
new file mode 100644
index 000000000..b7e2e06b8
--- /dev/null
+++ b/packages/contracts/src/contracts/current/test/TestLibMem/TestLibMem.sol
@@ -0,0 +1,56 @@
+/*
+
+ Copyright 2018 ZeroEx Intl.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+pragma solidity ^0.4.24;
+
+import "../../utils/LibMem/LibMem.sol";
+
+contract TestLibMem is
+ LibMem
+{
+
+ /// @dev Copies a block of memory from one location to another.
+ /// @param mem Memory contents we want to apply memCopy to
+ /// @param dest Destination offset into <mem>.
+ /// @param source Source offset into <mem>.
+ /// @param length Length of bytes to copy from <source> to <dest>
+ /// @return mem Memory contents after calling memCopy.
+ function testMemcpy(
+ bytes mem,
+ uint256 dest,
+ uint256 source,
+ uint256 length
+ )
+ public // not external, we need input in memory
+ pure
+ returns (bytes)
+ {
+ // Sanity check. Overflows are not checked.
+ require(source + length <= mem.length);
+ require(dest + length <= mem.length);
+
+ // Get pointer to memory contents
+ uint256 offset = getMemAddress(mem) + 32;
+
+ // Execute memCopy adjusted for memory array location
+ memCopy(offset + dest, offset + source, length);
+
+ // Return modified memory contents
+ return mem;
+ }
+}
diff --git a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
index df2221c93..d1d10476f 100644
--- a/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
+++ b/packages/contracts/src/contracts/current/utils/LibBytes/LibBytes.sol
@@ -18,14 +18,18 @@
pragma solidity ^0.4.24;
-contract LibBytes {
+import "../LibMem/LibMem.sol";
+
+contract LibBytes is
+ LibMem
+{
// Revert reasons
- string constant GT_ZERO_LENGTH_REQUIRED = "Length must be greater than 0.";
- string constant GTE_4_LENGTH_REQUIRED = "Length must be greater than or equal to 4.";
- 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.";
- string constant INDEX_OUT_OF_BOUNDS = "Specified array index is out of bounds.";
+ string constant GREATER_THAN_ZERO_LENGTH_REQUIRED = "GREATER_THAN_ZERO_LENGTH_REQUIRED";
+ string constant GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED";
+ string constant GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED";
+ string constant GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED";
+ string constant GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED = "GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED";
/// @dev Pops the last byte off of a byte array by modifying its length.
/// @param b Byte array that will be modified.
@@ -37,12 +41,12 @@ contract LibBytes {
{
require(
b.length > 0,
- GT_ZERO_LENGTH_REQUIRED
+ GREATER_THAN_ZERO_LENGTH_REQUIRED
);
// Store last byte.
result = b[b.length - 1];
-
+
assembly {
// Decrement length of byte array.
let newLen := sub(mload(b), 1)
@@ -61,7 +65,7 @@ contract LibBytes {
{
require(
b.length >= 20,
- GTE_20_LENGTH_REQUIRED
+ GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED
);
// Store last 20 bytes.
@@ -124,8 +128,8 @@ contract LibBytes {
{
require(
b.length >= index + 20, // 20 is length of address
- GTE_20_LENGTH_REQUIRED
- );
+ GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED
+ );
// Add offset to index:
// 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
@@ -156,8 +160,8 @@ contract LibBytes {
{
require(
b.length >= index + 20, // 20 is length of address
- GTE_20_LENGTH_REQUIRED
- );
+ GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED
+ );
// Add offset to index:
// 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
@@ -195,7 +199,7 @@ contract LibBytes {
{
require(
b.length >= index + 32,
- GTE_32_LENGTH_REQUIRED
+ GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED
);
// Arrays are prefixed by a 256 bit length parameter
@@ -222,7 +226,7 @@ contract LibBytes {
{
require(
b.length >= index + 32,
- GTE_32_LENGTH_REQUIRED
+ GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED
);
// Arrays are prefixed by a 256 bit length parameter
@@ -274,11 +278,72 @@ contract LibBytes {
{
require(
b.length >= 4,
- GTE_4_LENGTH_REQUIRED
+ GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED
);
assembly {
result := mload(add(b, 32))
}
return result;
}
+
+ /// @dev Reads nested bytes from a specific position.
+ /// @param b Byte array containing nested bytes.
+ /// @param index Index of nested bytes.
+ /// @return result Nested bytes.
+ function readBytes(
+ bytes memory b,
+ uint256 index
+ )
+ internal
+ pure
+ returns (bytes memory result)
+ {
+ // Read length of nested bytes
+ uint256 nestedBytesLength = readUint256(b, index);
+ index += 32;
+
+ // Assert length of <b> is valid, given
+ // length of nested bytes
+ require(
+ b.length >= index + nestedBytesLength,
+ GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED
+ );
+
+ // Allocate memory and copy value to result
+ result = new bytes(nestedBytesLength);
+ memCopy(
+ getMemAddress(result) + 32, // +32 skips array length
+ getMemAddress(b) + index + 32,
+ nestedBytesLength
+ );
+
+ return result;
+ }
+
+ /// @dev Inserts bytes at 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 bytes to insert.
+ function writeBytes(
+ bytes memory b,
+ uint256 index,
+ bytes memory input
+ )
+ internal
+ pure
+ {
+ // Assert length of <b> is valid, given
+ // length of input
+ require(
+ b.length >= index + 32 /* 32 bytes to store length */ + input.length,
+ GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED
+ );
+
+ // Copy <input> into <b>
+ memCopy(
+ getMemAddress(b) + 32 + index, // +32 to skip length of <b>
+ getMemAddress(input), // includes length of <input>
+ input.length + 32 // +32 bytes to store <input> length
+ );
+ }
}
diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol
new file mode 100644
index 000000000..6afb9973a
--- /dev/null
+++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol
@@ -0,0 +1,140 @@
+/*
+
+ Copyright 2018 ZeroEx Intl.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+pragma solidity ^0.4.24;
+
+contract LibMem
+{
+
+ /// @dev Gets the memory address for a byte array.
+ /// @param input Byte array to lookup.
+ /// @return memoryAddress Memory address of byte array.
+ function getMemAddress(bytes memory input)
+ internal
+ pure
+ returns (uint256 memoryAddress)
+ {
+ assembly {
+ memoryAddress := input
+ }
+ return memoryAddress;
+ }
+
+ /// @dev Copies `length` bytes from memory location `source` to `dest`.
+ /// @param dest memory address to copy bytes to.
+ /// @param source memory address to copy bytes from.
+ /// @param length number of bytes to copy.
+ function memCopy(
+ uint256 dest,
+ uint256 source,
+ uint256 length
+ )
+ internal
+ pure
+ {
+ if (length < 32) {
+ // Handle a partial word by reading destination and masking
+ // off the bits we are interested in.
+ // This correctly handles overlap, zero lengths and source == dest
+ assembly {
+ let mask := sub(exp(256, sub(32, length)), 1)
+ let s := and(mload(source), not(mask))
+ let d := and(mload(dest), mask)
+ mstore(dest, or(s, d))
+ }
+ } else {
+ // Skip the O(length) loop when source == dest.
+ if (source == dest) {
+ return;
+ }
+
+ // For large copies we copy whole words at a time. The final
+ // word is aligned to the end of the range (instead of after the
+ // previous) to handle partial words. So a copy will look like this:
+ //
+ // ####
+ // ####
+ // ####
+ // ####
+ //
+ // We handle overlap in the source and destination range by
+ // changing the copying direction. This prevents us from
+ // overwriting parts of source that we still need to copy.
+ //
+ // This correctly handles source == dest
+ //
+ if (source > dest) {
+ assembly {
+ // Record the total number of full words to copy
+ let nWords := div(length, 32)
+
+ // We subtract 32 from `sEnd` and `dEnd` because it
+ // is easier to compare with in the loop, and these
+ // are also the addresses we need for copying the
+ // last bytes.
+ length := sub(length, 32)
+ let sEnd := add(source, length)
+ let dEnd := add(dest, length)
+
+ // Remember the last 32 bytes of source
+ // This needs to be done here and not after the loop
+ // because we may have overwritten the last bytes in
+ // source already due to overlap.
+ let last := mload(sEnd)
+
+ // Copy whole words front to back
+ for {let i := 0} lt(i, nWords) {i := add(i, 1)} {
+ mstore(dest, mload(source))
+ source := add(source, 32)
+ dest := add(dest, 32)
+ }
+
+ // Write the last 32 bytes
+ mstore(dEnd, last)
+ }
+ } else {
+ assembly {
+ // Record the total number of full words to copy
+ let nWords := div(length, 32)
+
+ // We subtract 32 from `sEnd` and `dEnd` because those
+ // are the starting points when copying a word at the end.
+ length := sub(length, 32)
+ let sEnd := add(source, length)
+ let dEnd := add(dest, length)
+
+ // Remember the first 32 bytes of source
+ // This needs to be done here and not after the loop
+ // because we may have overwritten the first bytes in
+ // source already due to overlap.
+ let first := mload(source)
+
+ // Copy whole words back to front
+ for {let i := 0} lt(i, nWords) {i := add(i, 1)} {
+ mstore(dEnd, mload(sEnd))
+ sEnd := sub(sEnd, 32)
+ dEnd := sub(dEnd, 32)
+ }
+
+ // Write the first 32 bytes
+ mstore(dest, first)
+ }
+ }
+ }
+ }
+}
diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts
index 357c66a0a..bf7221d6d 100644
--- a/packages/contracts/src/utils/artifacts.ts
+++ b/packages/contracts/src/utils/artifacts.ts
@@ -2,6 +2,7 @@ import { ContractArtifact } from '@0xproject/sol-compiler';
import * as AssetProxyOwner from '../artifacts/AssetProxyOwner.json';
import * as DummyERC20Token from '../artifacts/DummyERC20Token.json';
+import * as DummyERC721Receiver from '../artifacts/DummyERC721Receiver.json';
import * as DummyERC721Token from '../artifacts/DummyERC721Token.json';
import * as ERC20Proxy from '../artifacts/ERC20Proxy.json';
import * as ERC721Proxy from '../artifacts/ERC721Proxy.json';
@@ -9,8 +10,10 @@ import * as Exchange from '../artifacts/Exchange.json';
import * as MixinAuthorizable from '../artifacts/MixinAuthorizable.json';
import * as MultiSigWallet from '../artifacts/MultiSigWallet.json';
import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json';
+import * as TestAssetDataDecoders from '../artifacts/TestAssetDataDecoders.json';
import * as TestAssetProxyDispatcher from '../artifacts/TestAssetProxyDispatcher.json';
import * as TestLibBytes from '../artifacts/TestLibBytes.json';
+import * as TestLibMem from '../artifacts/TestLibMem.json';
import * as TestLibs from '../artifacts/TestLibs.json';
import * as TestSignatureValidator from '../artifacts/TestSignatureValidator.json';
import * as TokenRegistry from '../artifacts/TokenRegistry.json';
@@ -21,6 +24,7 @@ import * as ZRX from '../artifacts/ZRXToken.json';
export const artifacts = {
AssetProxyOwner: (AssetProxyOwner as any) as ContractArtifact,
DummyERC20Token: (DummyERC20Token as any) as ContractArtifact,
+ DummyERC721Receiver: (DummyERC721Receiver as any) as ContractArtifact,
DummyERC721Token: (DummyERC721Token as any) as ContractArtifact,
ERC20Proxy: (ERC20Proxy as any) as ContractArtifact,
ERC721Proxy: (ERC721Proxy as any) as ContractArtifact,
@@ -30,7 +34,9 @@ export const artifacts = {
MultiSigWallet: (MultiSigWallet as any) as ContractArtifact,
MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact,
TestAssetProxyDispatcher: (TestAssetProxyDispatcher as any) as ContractArtifact,
+ TestAssetDataDecoders: (TestAssetDataDecoders as any) as ContractArtifact,
TestLibBytes: (TestLibBytes as any) as ContractArtifact,
+ TestLibMem: (TestLibMem as any) as ContractArtifact,
TestLibs: (TestLibs as any) as ContractArtifact,
TestSignatureValidator: (TestSignatureValidator as any) as ContractArtifact,
TokenRegistry: (TokenRegistry as any) as ContractArtifact,
diff --git a/packages/contracts/src/utils/constants.ts b/packages/contracts/src/utils/constants.ts
index fa2a4af3c..af3f26d82 100644
--- a/packages/contracts/src/utils/constants.ts
+++ b/packages/contracts/src/utils/constants.ts
@@ -19,11 +19,11 @@ const TESTRPC_PRIVATE_KEYS_STRINGS = [
export const constants = {
INVALID_OPCODE: 'invalid opcode',
REVERT: 'revert',
- LIB_BYTES_GT_ZERO_LENGTH_REQUIRED: 'Length must be greater than 0.',
- LIB_BYTES_GTE_4_LENGTH_REQUIRED: 'Length must be greater than or equal to 4.',
- LIB_BYTES_GTE_20_LENGTH_REQUIRED: 'Length must be greater than or equal to 20.',
- LIB_BYTES_GTE_32_LENGTH_REQUIRED: 'Length must be greater than or equal to 32.',
- LIB_BYTES_INDEX_OUT_OF_BOUNDS: 'Specified array index is out of bounds.',
+ LIB_BYTES_GREATER_THAN_ZERO_LENGTH_REQUIRED: 'GREATER_THAN_ZERO_LENGTH_REQUIRED',
+ LIB_BYTES_GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED',
+ LIB_BYTES_GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED',
+ LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED',
+ LIB_BYTES_GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED: 'GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED',
ERC20_INSUFFICIENT_BALANCE: 'Insufficient balance to complete transfer.',
ERC20_INSUFFICIENT_ALLOWANCE: 'Insufficient allowance to complete transfer.',
TESTRPC_NETWORK_ID: 50,
diff --git a/packages/contracts/src/utils/match_order_tester.ts b/packages/contracts/src/utils/match_order_tester.ts
index f4f7f965b..fbb1b99db 100644
--- a/packages/contracts/src/utils/match_order_tester.ts
+++ b/packages/contracts/src/utils/match_order_tester.ts
@@ -237,11 +237,11 @@ export class MatchOrderTester {
const expectedNewERC20BalancesByOwner = _.cloneDeep(erc20BalancesByOwner);
const expectedNewERC721TokenIdsByOwner = _.cloneDeep(erc721TokenIdsByOwner);
// Left Maker Asset (Right Taker Asset)
- const makerAssetProxyIdLeft = assetProxyUtils.decodeProxyDataId(signedOrderLeft.makerAssetData);
+ const makerAssetProxyIdLeft = assetProxyUtils.decodeAssetDataId(signedOrderLeft.makerAssetData);
if (makerAssetProxyIdLeft === AssetProxyId.ERC20) {
// Decode asset data
- const erc20ProxyData = assetProxyUtils.decodeERC20ProxyData(signedOrderLeft.makerAssetData);
- const makerAssetAddressLeft = erc20ProxyData.tokenAddress;
+ const erc20AssetData = assetProxyUtils.decodeERC20AssetData(signedOrderLeft.makerAssetData);
+ const makerAssetAddressLeft = erc20AssetData.tokenAddress;
const takerAssetAddressRight = makerAssetAddressLeft;
// Left Maker
expectedNewERC20BalancesByOwner[makerAddressLeft][makerAssetAddressLeft] = expectedNewERC20BalancesByOwner[
@@ -259,9 +259,9 @@ export class MatchOrderTester {
][makerAssetAddressLeft].add(expectedTransferAmounts.amountReceivedByTaker);
} else if (makerAssetProxyIdLeft === AssetProxyId.ERC721) {
// Decode asset data
- const erc721ProxyData = assetProxyUtils.decodeERC721ProxyData(signedOrderLeft.makerAssetData);
- const makerAssetAddressLeft = erc721ProxyData.tokenAddress;
- const makerAssetIdLeft = erc721ProxyData.tokenId;
+ const erc721AssetData = assetProxyUtils.decodeERC721AssetData(signedOrderLeft.makerAssetData);
+ const makerAssetAddressLeft = erc721AssetData.tokenAddress;
+ const makerAssetIdLeft = erc721AssetData.tokenId;
const takerAssetAddressRight = makerAssetAddressLeft;
const takerAssetIdRight = makerAssetIdLeft;
// Left Maker
@@ -272,11 +272,11 @@ export class MatchOrderTester {
}
// Left Taker Asset (Right Maker Asset)
// Note: This exchange is only between the order makers: the Taker does not receive any of the left taker asset.
- const takerAssetProxyIdLeft = assetProxyUtils.decodeProxyDataId(signedOrderLeft.takerAssetData);
+ const takerAssetProxyIdLeft = assetProxyUtils.decodeAssetDataId(signedOrderLeft.takerAssetData);
if (takerAssetProxyIdLeft === AssetProxyId.ERC20) {
// Decode asset data
- const erc20ProxyData = assetProxyUtils.decodeERC20ProxyData(signedOrderLeft.takerAssetData);
- const takerAssetAddressLeft = erc20ProxyData.tokenAddress;
+ const erc20AssetData = assetProxyUtils.decodeERC20AssetData(signedOrderLeft.takerAssetData);
+ const takerAssetAddressLeft = erc20AssetData.tokenAddress;
const makerAssetAddressRight = takerAssetAddressLeft;
// Left Maker
expectedNewERC20BalancesByOwner[makerAddressLeft][takerAssetAddressLeft] = expectedNewERC20BalancesByOwner[
@@ -290,9 +290,9 @@ export class MatchOrderTester {
);
} else if (takerAssetProxyIdLeft === AssetProxyId.ERC721) {
// Decode asset data
- const erc721ProxyData = assetProxyUtils.decodeERC721ProxyData(signedOrderRight.makerAssetData);
- const makerAssetAddressRight = erc721ProxyData.tokenAddress;
- const makerAssetIdRight = erc721ProxyData.tokenId;
+ const erc721AssetData = assetProxyUtils.decodeERC721AssetData(signedOrderRight.makerAssetData);
+ const makerAssetAddressRight = erc721AssetData.tokenAddress;
+ const makerAssetIdRight = erc721AssetData.tokenId;
const takerAssetAddressLeft = makerAssetAddressRight;
const takerAssetIdLeft = makerAssetIdRight;
// Right Maker
diff --git a/packages/contracts/src/utils/types.ts b/packages/contracts/src/utils/types.ts
index 491890fa1..bb8c12088 100644
--- a/packages/contracts/src/utils/types.ts
+++ b/packages/contracts/src/utils/types.ts
@@ -90,11 +90,14 @@ export enum ContractName {
AccountLevels = 'AccountLevels',
EtherDelta = 'EtherDelta',
Arbitrage = 'Arbitrage',
+ TestAssetDataDecoders = 'TestAssetDataDecoders',
TestAssetProxyDispatcher = 'TestAssetProxyDispatcher',
+ TestLibMem = 'TestLibMem',
TestLibs = 'TestLibs',
TestSignatureValidator = 'TestSignatureValidator',
ERC20Proxy = 'ERC20Proxy',
ERC721Proxy = 'ERC721Proxy',
+ DummyERC721Receiver = 'DummyERC721Receiver',
DummyERC721Token = 'DummyERC721Token',
TestLibBytes = 'TestLibBytes',
Authorizable = 'Authorizable',
diff --git a/packages/contracts/test/asset_proxy/decoder.ts b/packages/contracts/test/asset_proxy/decoder.ts
new file mode 100644
index 000000000..d4fae1601
--- /dev/null
+++ b/packages/contracts/test/asset_proxy/decoder.ts
@@ -0,0 +1,103 @@
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+import ethUtil = require('ethereumjs-util');
+
+import { TestAssetDataDecodersContract } from '../../src/generated_contract_wrappers/test_asset_data_decoders';
+import { artifacts } from '../../src/utils/artifacts';
+import { chaiSetup } from '../../src/utils/chai_setup';
+import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
+
+chaiSetup.configure();
+const expect = chai.expect;
+const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+
+describe('TestAssetDataDecoders', () => {
+ let testAssetProxyDecoder: TestAssetDataDecodersContract;
+ let testAddress: string;
+
+ before(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ after(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+ before(async () => {
+ // Setup accounts & addresses
+ const accounts = await web3Wrapper.getAvailableAddressesAsync();
+ testAddress = accounts[0];
+ // Deploy TestLibMem
+ testAssetProxyDecoder = await TestAssetDataDecodersContract.deployFrom0xArtifactAsync(
+ artifacts.TestAssetDataDecoders,
+ provider,
+ txDefaults,
+ );
+ });
+ beforeEach(async () => {
+ await blockchainLifecycle.startAsync();
+ });
+ afterEach(async () => {
+ await blockchainLifecycle.revertAsync();
+ });
+
+ describe('Asset Data Decoders', () => {
+ it('should correctly decode ERC20 asset data)', async () => {
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(testAddress);
+ const expectedDecodedAssetData = assetProxyUtils.decodeERC20AssetData(encodedAssetData);
+ let decodedAssetProxyId: number;
+ let decodedTokenAddress: string;
+ [decodedAssetProxyId, decodedTokenAddress] = await testAssetProxyDecoder.publicDecodeERC20Data.callAsync(
+ encodedAssetData,
+ );
+ expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId);
+ expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress);
+ });
+
+ it('should correctly decode ERC721 asset data', async () => {
+ const tokenId = generatePseudoRandomSalt();
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId);
+ const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData);
+ let decodedAssetProxyId: number;
+ let decodedTokenAddress: string;
+ let decodedTokenId: BigNumber;
+ let decodedData: string;
+ [
+ decodedAssetProxyId,
+ decodedTokenAddress,
+ decodedTokenId,
+ decodedData,
+ ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedAssetData);
+ expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId);
+ expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress);
+ expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedAssetData.tokenId);
+ expect(decodedData).to.be.equal(expectedDecodedAssetData.receiverData);
+ });
+
+ it('should correctly decode ERC721 asset data with receiver data', async () => {
+ const tokenId = generatePseudoRandomSalt();
+ const receiverDataFirst32Bytes = ethUtil.bufferToHex(
+ assetProxyUtils.encodeUint256(generatePseudoRandomSalt()),
+ );
+ const receiverDataExtraBytes = 'FFFF';
+ // We add extra bytes to generate a value that doesn't fit perfectly into one word
+ const receiverData = receiverDataFirst32Bytes + receiverDataExtraBytes;
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(testAddress, tokenId, receiverData);
+ const expectedDecodedAssetData = assetProxyUtils.decodeERC721AssetData(encodedAssetData);
+ let decodedAssetProxyId: number;
+ let decodedTokenAddress: string;
+ let decodedTokenId: BigNumber;
+ let decodedReceiverData: string;
+ [
+ decodedAssetProxyId,
+ decodedTokenAddress,
+ decodedTokenId,
+ decodedReceiverData,
+ ] = await testAssetProxyDecoder.publicDecodeERC721Data.callAsync(encodedAssetData);
+ expect(decodedAssetProxyId).to.be.equal(expectedDecodedAssetData.assetProxyId);
+ expect(decodedTokenAddress).to.be.equal(expectedDecodedAssetData.tokenAddress);
+ expect(decodedTokenId).to.be.bignumber.equal(expectedDecodedAssetData.tokenId);
+ expect(decodedReceiverData).to.be.equal(expectedDecodedAssetData.receiverData);
+ });
+ });
+});
diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts
index d14280c5f..08376ccfb 100644
--- a/packages/contracts/test/asset_proxy/proxies.ts
+++ b/packages/contracts/test/asset_proxy/proxies.ts
@@ -1,24 +1,33 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
-import { assetProxyUtils } from '@0xproject/order-utils';
+import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
+import { LogWithDecodedArgs } from 'ethereum-types';
+import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token';
+import {
+ DummyERC721ReceiverContract,
+ TokenReceivedContractEventArgs,
+} from '../../src/generated_contract_wrappers/dummy_e_r_c721_receiver';
import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy';
+import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
-import { provider, web3Wrapper } from '../../src/utils/web3_wrapper';
+import { LogDecoder } from '../../src/utils/log_decoder';
+import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+// tslint:disable:no-unnecessary-type-assertion
describe('Asset Transfer Proxies', () => {
let owner: string;
let notAuthorized: string;
@@ -28,6 +37,7 @@ describe('Asset Transfer Proxies', () => {
let zrxToken: DummyERC20TokenContract;
let erc721Token: DummyERC721TokenContract;
+ let erc721Receiver: DummyERC721ReceiverContract;
let erc20Proxy: ERC20ProxyContract;
let erc721Proxy: ERC721ProxyContract;
@@ -69,6 +79,11 @@ describe('Asset Transfer Proxies', () => {
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
+ erc721Receiver = await DummyERC721ReceiverContract.deployFrom0xArtifactAsync(
+ artifacts.DummyERC721Receiver,
+ provider,
+ txDefaults,
+ );
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -79,14 +94,14 @@ describe('Asset Transfer Proxies', () => {
describe('Transfer Proxy - ERC20', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
- // Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ // Construct ERC20 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -105,14 +120,14 @@ describe('Asset Transfer Proxies', () => {
});
it('should do nothing if transferring 0 amount of a token', async () => {
- // Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ // Construct ERC20 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -131,8 +146,8 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if allowances are too low', async () => {
- // Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ // Construct ERC20 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0);
const transferAmount = new BigNumber(10);
@@ -145,7 +160,7 @@ describe('Asset Transfer Proxies', () => {
// Perform a transfer; expect this to fail.
return expectRevertOrAlwaysFailingTransactionAsync(
erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
transferAmount,
@@ -155,20 +170,14 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if requesting address is not authorized', async () => {
- // Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ // Construct ERC20 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10);
return expectRevertOrAlwaysFailingTransactionAsync(
- erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
- makerAddress,
- takerAddress,
- amount,
- {
- from: notAuthorized,
- },
- ),
+ erc20Proxy.transferFrom.sendTransactionAsync(encodedAssetData, makerAddress, takerAddress, amount, {
+ from: notAuthorized,
+ }),
);
});
});
@@ -177,16 +186,16 @@ describe('Asset Transfer Proxies', () => {
it('should succesfully make multiple token transfers', async () => {
const erc20Balances = await erc20Wrapper.getBalancesAsync();
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const amount = new BigNumber(10);
const numTransfers = 2;
- const assetMetadata = _.times(numTransfers, () => encodedProxyMetadata);
+ const assetData = _.times(numTransfers, () => encodedAssetData);
const fromAddresses = _.times(numTransfers, () => makerAddress);
const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => amount);
const txHash = await erc20Proxy.batchTransferFrom.sendTransactionAsync(
- assetMetadata,
+ assetData,
fromAddresses,
toAddresses,
amounts,
@@ -208,22 +217,18 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if not called by an authorized address', async () => {
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const amount = new BigNumber(10);
const numTransfers = 2;
- const assetMetadata = _.times(numTransfers, () => encodedProxyMetadata);
+ const assetData = _.times(numTransfers, () => encodedAssetData);
const fromAddresses = _.times(numTransfers, () => makerAddress);
const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => amount);
return expectRevertOrAlwaysFailingTransactionAsync(
- erc20Proxy.batchTransferFrom.sendTransactionAsync(
- assetMetadata,
- fromAddresses,
- toAddresses,
- amounts,
- { from: notAuthorized },
- ),
+ erc20Proxy.batchTransferFrom.sendTransactionAsync(assetData, fromAddresses, toAddresses, amounts, {
+ from: notAuthorized,
+ }),
);
});
});
@@ -237,11 +242,8 @@ describe('Asset Transfer Proxies', () => {
describe('Transfer Proxy - ERC721', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
- erc721Token.address,
- erc721MakerTokenId,
- );
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -249,7 +251,7 @@ describe('Asset Transfer Proxies', () => {
const amount = new BigNumber(1);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -262,12 +264,94 @@ describe('Asset Transfer Proxies', () => {
expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress);
});
- it('should throw if transferring 0 amount of a token', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
+ it('should not call onERC721Received when transferring to a smart contract without receiver data', async () => {
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
+ // Verify pre-condition
+ const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
+ // Perform a transfer from makerAddress to takerAddress
+ const amount = new BigNumber(1);
+ const txHash = await erc721Proxy.transferFrom.sendTransactionAsync(
+ encodedAssetData,
+ makerAddress,
+ erc721Receiver.address,
+ amount,
+ { from: exchangeAddress },
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
+ // Parse transaction logs
+ const logDecoder = new LogDecoder(web3Wrapper, erc721Receiver.address);
+ const tx = await logDecoder.getTxWithDecodedLogsAsync(txHash);
+ // Verify that no log was emitted by erc721 receiver
+ expect(tx.logs.length).to.be.equal(0);
+ // Verify transfer was successful
+ const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address);
+ });
+
+ it('should call onERC721Received when transferring to a smart contract with receiver data', async () => {
+ // Construct ERC721 asset data
+ const receiverData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt()));
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(
+ erc721Token.address,
+ erc721MakerTokenId,
+ receiverData,
+ );
+ // Verify pre-condition
+ const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
+ // Perform a transfer from makerAddress to takerAddress
+ const amount = new BigNumber(1);
+ const txHash = await erc721Proxy.transferFrom.sendTransactionAsync(
+ encodedAssetData,
+ makerAddress,
+ erc721Receiver.address,
+ amount,
+ { from: exchangeAddress },
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
+ // Parse transaction logs
+ const logDecoder = new LogDecoder(web3Wrapper, erc721Receiver.address);
+ const tx = await logDecoder.getTxWithDecodedLogsAsync(txHash);
+ // Validate log emitted by erc721 receiver
+ expect(tx.logs.length).to.be.equal(1);
+ const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs<TokenReceivedContractEventArgs>;
+ expect(tokenReceivedLog.args.from).to.be.equal(makerAddress);
+ expect(tokenReceivedLog.args.tokenId).to.be.bignumber.equal(erc721MakerTokenId);
+ expect(tokenReceivedLog.args.data).to.be.equal(receiverData);
+ // Verify transfer was successful
+ const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address);
+ });
+
+ it('should throw if there is receiver data but contract does not have onERC721Received', async () => {
+ // Construct ERC721 asset data
+ const receiverData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt()));
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(
erc721Token.address,
erc721MakerTokenId,
+ receiverData,
+ );
+ // Verify pre-condition
+ const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
+ // Perform a transfer from makerAddress to takerAddress
+ const amount = new BigNumber(1);
+ return expectRevertOrAlwaysFailingTransactionAsync(
+ erc721Proxy.transferFrom.sendTransactionAsync(
+ encodedAssetData,
+ makerAddress,
+ erc20Proxy.address, // the ERC20 proxy does not have an ERC721 receiver
+ amount,
+ { from: exchangeAddress },
+ ),
);
+ });
+
+ it('should throw if transferring 0 amount of a token', async () => {
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -275,7 +359,7 @@ describe('Asset Transfer Proxies', () => {
const amount = new BigNumber(0);
return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -285,11 +369,8 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if transferring > 1 amount of a token', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
- erc721Token.address,
- erc721MakerTokenId,
- );
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -297,7 +378,7 @@ describe('Asset Transfer Proxies', () => {
const amount = new BigNumber(500);
return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -307,11 +388,8 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if allowances are too low', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
- erc721Token.address,
- erc721MakerTokenId,
- );
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Remove transfer approval for makerAddress.
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, false, {
@@ -322,29 +400,20 @@ describe('Asset Transfer Proxies', () => {
// Perform a transfer; expect this to fail.
const amount = new BigNumber(1);
return expectRevertOrAlwaysFailingTransactionAsync(
- erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
- makerAddress,
- takerAddress,
- amount,
- {
- from: notAuthorized,
- },
- ),
+ erc20Proxy.transferFrom.sendTransactionAsync(encodedAssetData, makerAddress, takerAddress, amount, {
+ from: notAuthorized,
+ }),
);
});
it('should throw if requesting address is not authorized', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
- erc721Token.address,
- erc721MakerTokenId,
- );
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(1);
return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -360,16 +429,16 @@ describe('Asset Transfer Proxies', () => {
const [makerTokenIdA, makerTokenIdB] = erc721TokensById[makerAddress][erc721Token.address];
const numTransfers = 2;
- const assetMetadata = [
- assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdA),
- assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdB),
+ const assetData = [
+ assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdA),
+ assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdB),
];
const fromAddresses = _.times(numTransfers, () => makerAddress);
const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => new BigNumber(1));
const txHash = await erc721Proxy.batchTransferFrom.sendTransactionAsync(
- assetMetadata,
+ assetData,
fromAddresses,
toAddresses,
amounts,
@@ -392,22 +461,18 @@ describe('Asset Transfer Proxies', () => {
const [makerTokenIdA, makerTokenIdB] = erc721TokensById[makerAddress][erc721Token.address];
const numTransfers = 2;
- const assetMetadata = [
- assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdA),
- assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdB),
+ const assetData = [
+ assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdA),
+ assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdB),
];
const fromAddresses = _.times(numTransfers, () => makerAddress);
const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => new BigNumber(1));
return expectRevertOrAlwaysFailingTransactionAsync(
- erc721Proxy.batchTransferFrom.sendTransactionAsync(
- assetMetadata,
- fromAddresses,
- toAddresses,
- amounts,
- { from: notAuthorized },
- ),
+ erc721Proxy.batchTransferFrom.sendTransactionAsync(assetData, fromAddresses, toAddresses, amounts, {
+ from: notAuthorized,
+ }),
);
});
});
@@ -418,3 +483,4 @@ describe('Asset Transfer Proxies', () => {
});
});
});
+// tslint:enable:no-unnecessary-type-assertion
diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts
index bee74cca8..53b98c755 100644
--- a/packages/contracts/test/exchange/core.ts
+++ b/packages/contracts/test/exchange/core.ts
@@ -87,7 +87,7 @@ describe('Exchange core', () => {
artifacts.Exchange,
provider,
txDefaults,
- assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ assetProxyUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner);
@@ -114,8 +114,8 @@ describe('Exchange core', () => {
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
@@ -711,8 +711,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1),
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -737,8 +737,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1),
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -759,8 +759,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1),
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -781,8 +781,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(2),
takerAssetAmount: new BigNumber(1),
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -803,8 +803,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(500),
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -825,8 +825,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(0),
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -846,8 +846,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -886,8 +886,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({
takerAssetAmount: new BigNumber(1),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId),
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress),
});
// Verify pre-conditions
const initialOwnerTakerAsset = await erc721Token.ownerOf.callAsync(takerAssetId);
diff --git a/packages/contracts/test/exchange/dispatcher.ts b/packages/contracts/test/exchange/dispatcher.ts
index 02d43a132..9e113e47d 100644
--- a/packages/contracts/test/exchange/dispatcher.ts
+++ b/packages/contracts/test/exchange/dispatcher.ts
@@ -275,13 +275,13 @@ describe('AssetProxyDispatcher', () => {
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
await web3Wrapper.awaitTransactionSuccessAsync(
await assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -301,12 +301,12 @@ describe('AssetProxyDispatcher', () => {
it('should throw if dispatching to unregistered proxy', async () => {
// Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10);
return expectRevertOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
diff --git a/packages/contracts/test/exchange/libs.ts b/packages/contracts/test/exchange/libs.ts
index b12934014..eff05981d 100644
--- a/packages/contracts/test/exchange/libs.ts
+++ b/packages/contracts/test/exchange/libs.ts
@@ -38,8 +38,8 @@ describe('Exchange libs', () => {
exchangeAddress: libs.address,
makerAddress,
feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts
index aab3308ae..18a46187f 100644
--- a/packages/contracts/test/exchange/match_orders.ts
+++ b/packages/contracts/test/exchange/match_orders.ts
@@ -96,7 +96,7 @@ describe('matchOrders', () => {
artifacts.Exchange,
provider,
txDefaults,
- assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ assetProxyUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner);
@@ -122,8 +122,8 @@ describe('matchOrders', () => {
const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS,
exchangeAddress: exchange.address,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
};
const privateKeyLeft = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddressLeft)];
orderFactoryLeft = new OrderFactory(privateKeyLeft, defaultOrderParams);
@@ -148,16 +148,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -182,16 +180,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -227,16 +223,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(20), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(4), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -261,16 +255,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -295,16 +287,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -334,8 +324,8 @@ describe('matchOrders', () => {
// branch in the contract twice for this test.
const signedOrderRight2 = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -364,8 +354,6 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressLeft,
@@ -373,8 +361,8 @@ describe('matchOrders', () => {
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -404,8 +392,6 @@ describe('matchOrders', () => {
// branch in the contract twice for this test.
const signedOrderLeft2 = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(50), 18),
feeRecipientAddress: feeRecipientAddressLeft,
@@ -437,16 +423,14 @@ describe('matchOrders', () => {
const feeRecipientAddress = feeRecipientAddressLeft;
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress,
@@ -465,16 +449,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -494,16 +476,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -523,16 +503,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -552,16 +530,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -581,16 +557,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: makerAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: makerAddressRight,
@@ -609,16 +583,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -635,16 +607,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -661,16 +631,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -691,16 +659,14 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -721,16 +687,16 @@ describe('matchOrders', () => {
// Create orders to match
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(5), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(2), 18),
feeRecipientAddress: feeRecipientAddressRight,
@@ -752,16 +718,16 @@ describe('matchOrders', () => {
const erc721TokenToTransfer = erc721LeftMakerAssetIds[0];
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
makerAssetAmount: new BigNumber(1),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20TakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: new BigNumber(1),
feeRecipientAddress: feeRecipientAddressRight,
@@ -787,16 +753,16 @@ describe('matchOrders', () => {
const erc721TokenToTransfer = erc721RightMakerAssetIds[0];
const signedOrderLeft = orderFactoryLeft.newSignedOrder({
makerAddress: makerAddressLeft,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
takerAssetAmount: new BigNumber(1),
feeRecipientAddress: feeRecipientAddressLeft,
});
const signedOrderRight = orderFactoryRight.newSignedOrder({
makerAddress: makerAddressRight,
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(defaultERC721AssetAddress, erc721TokenToTransfer),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultERC20MakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(defaultERC721AssetAddress, erc721TokenToTransfer),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetAmount: new BigNumber(1),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(10), 18),
feeRecipientAddress: feeRecipientAddressRight,
diff --git a/packages/contracts/test/exchange/signature_validator.ts b/packages/contracts/test/exchange/signature_validator.ts
index 79db620b4..c39fd6ee4 100644
--- a/packages/contracts/test/exchange/signature_validator.ts
+++ b/packages/contracts/test/exchange/signature_validator.ts
@@ -42,8 +42,8 @@ describe('MixinSignatureValidator', () => {
exchangeAddress: signatureValidator.address,
makerAddress,
feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(addressUtils.generatePseudoRandomAddress()),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts
index 7897fa558..12390ce01 100644
--- a/packages/contracts/test/exchange/transactions.ts
+++ b/packages/contracts/test/exchange/transactions.ts
@@ -72,7 +72,7 @@ describe('Exchange transactions', () => {
artifacts.Exchange,
provider,
txDefaults,
- assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ assetProxyUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner);
@@ -91,8 +91,8 @@ describe('Exchange transactions', () => {
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerTokenAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerTokenAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerTokenAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerTokenAddress),
};
makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
@@ -224,8 +224,8 @@ describe('Exchange transactions', () => {
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerTokenAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerTokenAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerTokenAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerTokenAddress),
};
whitelistOrderFactory = new OrderFactory(makerPrivateKey, defaultOrderParams);
});
diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts
index 258e1ff81..b66cff90a 100644
--- a/packages/contracts/test/exchange/wrapper.ts
+++ b/packages/contracts/test/exchange/wrapper.ts
@@ -81,7 +81,7 @@ describe('Exchange wrappers', () => {
artifacts.Exchange,
provider,
txDefaults,
- assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ assetProxyUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner);
@@ -108,8 +108,8 @@ describe('Exchange wrappers', () => {
exchangeAddress: exchange.address,
makerAddress,
feeRecipientAddress,
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultMakerAssetAddress),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(defaultTakerAssetAddress),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(defaultMakerAssetAddress),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(defaultTakerAssetAddress),
};
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
@@ -304,7 +304,7 @@ describe('Exchange wrappers', () => {
const signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: makerZRXBalance,
makerFee: new BigNumber(1),
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
});
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
@@ -316,7 +316,7 @@ describe('Exchange wrappers', () => {
const signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(makerZRXAllowance),
makerFee: new BigNumber(1),
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
});
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
@@ -328,7 +328,7 @@ describe('Exchange wrappers', () => {
const signedOrder = orderFactory.newSignedOrder({
takerAssetAmount: takerZRXBalance,
takerFee: new BigNumber(1),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
});
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
@@ -340,7 +340,7 @@ describe('Exchange wrappers', () => {
const signedOrder = orderFactory.newSignedOrder({
takerAssetAmount: new BigNumber(takerZRXAllowance),
takerFee: new BigNumber(1),
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
});
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress);
const newBalances = await erc20Wrapper.getBalancesAsync();
@@ -354,8 +354,8 @@ describe('Exchange wrappers', () => {
const signedOrder = orderFactory.newSignedOrder({
makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1),
- makerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerAssetId),
- takerAssetData: assetProxyUtils.encodeERC721ProxyData(erc721Token.address, takerAssetId),
+ makerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerAssetId),
+ takerAssetData: assetProxyUtils.encodeERC721AssetData(erc721Token.address, takerAssetId),
});
// Verify pre-conditions
const initialOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@@ -692,7 +692,7 @@ describe('Exchange wrappers', () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
}),
orderFactory.newSignedOrder(),
];
@@ -785,7 +785,7 @@ describe('Exchange wrappers', () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
- takerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ takerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
}),
orderFactory.newSignedOrder(),
];
@@ -874,7 +874,7 @@ describe('Exchange wrappers', () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
}),
orderFactory.newSignedOrder(),
];
@@ -967,7 +967,7 @@ describe('Exchange wrappers', () => {
signedOrders = [
orderFactory.newSignedOrder(),
orderFactory.newSignedOrder({
- makerAssetData: assetProxyUtils.encodeERC20ProxyData(zrxToken.address),
+ makerAssetData: assetProxyUtils.encodeERC20AssetData(zrxToken.address),
}),
orderFactory.newSignedOrder(),
];
diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts
index 0996cdc84..2fefb7aeb 100644
--- a/packages/contracts/test/libraries/lib_bytes.ts
+++ b/packages/contracts/test/libraries/lib_bytes.ts
@@ -1,4 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
+import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { BigNumber } from '@0xproject/utils';
import BN = require('bn.js');
import * as chai from 'chai';
@@ -28,6 +29,15 @@ describe('LibBytes', () => {
let testAddress: string;
const testBytes32 = '0x102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f01020';
const testUint256 = new BigNumber(testBytes32, 16);
+ let shortData: string;
+ let shortTestBytes: string;
+ let shortTestBytesAsBuffer: Buffer;
+ let wordOfData: string;
+ let wordOfTestBytes: string;
+ let wordOfTestBytesAsBuffer: Buffer;
+ let longData: string;
+ let longTestBytes: string;
+ let longTestBytesAsBuffer: Buffer;
before(async () => {
await blockchainLifecycle.startAsync();
@@ -48,6 +58,26 @@ describe('LibBytes', () => {
expect(byteArrayLongerThan32BytesLength).to.be.greaterThan(32);
const testBytes32Length = ethUtil.toBuffer(testBytes32).byteLength;
expect(testBytes32Length).to.be.equal(32);
+ // Create short test bytes
+ shortData = '0xffffaa';
+ const encodedShortData = ethUtil.toBuffer(shortData);
+ const shortDataLength = new BigNumber(encodedShortData.byteLength);
+ const encodedShortDataLength = assetProxyUtils.encodeUint256(shortDataLength);
+ shortTestBytesAsBuffer = Buffer.concat([encodedShortDataLength, encodedShortData]);
+ shortTestBytes = ethUtil.bufferToHex(shortTestBytesAsBuffer);
+ // Create test bytes one word in length
+ wordOfData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt()));
+ const encodedWordOfData = ethUtil.toBuffer(wordOfData);
+ const wordOfDataLength = new BigNumber(encodedWordOfData.byteLength);
+ const encodedWordOfDataLength = assetProxyUtils.encodeUint256(wordOfDataLength);
+ wordOfTestBytesAsBuffer = Buffer.concat([encodedWordOfDataLength, encodedWordOfData]);
+ wordOfTestBytes = ethUtil.bufferToHex(wordOfTestBytesAsBuffer);
+ // Create long test bytes (combines short test bytes with word of test bytes)
+ longData = ethUtil.bufferToHex(Buffer.concat([encodedShortData, encodedWordOfData]));
+ const longDataLength = new BigNumber(encodedShortData.byteLength + encodedWordOfData.byteLength);
+ const encodedLongDataLength = assetProxyUtils.encodeUint256(longDataLength);
+ longTestBytesAsBuffer = Buffer.concat([encodedLongDataLength, encodedShortData, encodedWordOfData]);
+ longTestBytes = ethUtil.bufferToHex(longTestBytesAsBuffer);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -60,7 +90,7 @@ describe('LibBytes', () => {
it('should revert if length is 0', async () => {
return expectRevertOrOtherErrorAsync(
libBytes.publicPopByte.callAsync(constants.NULL_BYTES),
- constants.LIB_BYTES_GT_ZERO_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_THAN_ZERO_LENGTH_REQUIRED,
);
});
@@ -77,7 +107,7 @@ describe('LibBytes', () => {
it('should revert if length is less than 20', async () => {
return expectRevertOrOtherErrorAsync(
libBytes.publicPopAddress.callAsync(byteArrayShorterThan20Bytes),
- constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED,
);
});
@@ -163,7 +193,7 @@ describe('LibBytes', () => {
const offset = new BigNumber(0);
return expectRevertOrOtherErrorAsync(
libBytes.publicReadAddress.callAsync(shortByteArray, offset),
- constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED,
);
});
@@ -172,7 +202,7 @@ describe('LibBytes', () => {
const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength);
return expectRevertOrOtherErrorAsync(
libBytes.publicReadAddress.callAsync(byteArray, badOffset),
- constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_20_LENGTH_REQUIRED,
);
});
});
@@ -209,7 +239,7 @@ describe('LibBytes', () => {
const offset = new BigNumber(0);
return expectRevertOrOtherErrorAsync(
libBytes.publicReadBytes32.callAsync(byteArrayShorterThan32Bytes, offset),
- constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED,
);
});
@@ -217,7 +247,7 @@ describe('LibBytes', () => {
const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength);
return expectRevertOrOtherErrorAsync(
libBytes.publicReadBytes32.callAsync(testBytes32, badOffset),
- constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED,
);
});
});
@@ -258,7 +288,7 @@ describe('LibBytes', () => {
const offset = new BigNumber(0);
return expectRevertOrOtherErrorAsync(
libBytes.publicReadUint256.callAsync(byteArrayShorterThan32Bytes, offset),
- constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED,
);
});
@@ -269,7 +299,7 @@ describe('LibBytes', () => {
const badOffset = new BigNumber(testUint256AsBuffer.byteLength);
return expectRevertOrOtherErrorAsync(
libBytes.publicReadUint256.callAsync(byteArray, badOffset),
- constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED,
);
});
});
@@ -291,7 +321,7 @@ describe('LibBytes', () => {
const byteArrayLessThan4Bytes = '0x010101';
return expectRevertOrOtherErrorAsync(
libBytes.publicReadFirst4.callAsync(byteArrayLessThan4Bytes),
- constants.LIB_BYTES_GTE_4_LENGTH_REQUIRED,
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_4_LENGTH_REQUIRED,
);
});
it('should return the first 4 bytes of a byte array of arbitrary length', async () => {
@@ -300,4 +330,180 @@ describe('LibBytes', () => {
expect(first4Bytes).to.equal(expectedFirst4Bytes);
});
});
+
+ describe('readBytes', () => {
+ it('should successfully read short, nested array of bytes when it takes up the whole array', async () => {
+ const testBytesOffset = new BigNumber(0);
+ const bytes = await libBytes.publicReadBytes.callAsync(shortTestBytes, testBytesOffset);
+ return expect(bytes).to.be.equal(shortData);
+ });
+
+ it('should successfully read short, nested array of bytes when it is offset in the array', async () => {
+ const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef');
+ const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, shortTestBytesAsBuffer]);
+ const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
+ const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength);
+ const bytes = await libBytes.publicReadBytes.callAsync(combinedByteArray, testUint256Offset);
+ return expect(bytes).to.be.equal(shortData);
+ });
+
+ it('should successfully read a nested array of bytes - one word in length - when it takes up the whole array', async () => {
+ const testBytesOffset = new BigNumber(0);
+ const bytes = await libBytes.publicReadBytes.callAsync(wordOfTestBytes, testBytesOffset);
+ return expect(bytes).to.be.equal(wordOfData);
+ });
+
+ it('should successfully read a nested array of bytes - one word in length - when it is offset in the array', async () => {
+ const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef');
+ const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, wordOfTestBytesAsBuffer]);
+ const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
+ const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength);
+ const bytes = await libBytes.publicReadBytes.callAsync(combinedByteArray, testUint256Offset);
+ return expect(bytes).to.be.equal(wordOfData);
+ });
+
+ it('should successfully read long, nested array of bytes when it takes up the whole array', async () => {
+ const testBytesOffset = new BigNumber(0);
+ const bytes = await libBytes.publicReadBytes.callAsync(longTestBytes, testBytesOffset);
+ return expect(bytes).to.be.equal(longData);
+ });
+
+ it('should successfully read long, nested array of bytes when it is offset in the array', async () => {
+ const prefixByteArrayBuffer = ethUtil.toBuffer('0xabcdef');
+ const combinedByteArrayBuffer = Buffer.concat([prefixByteArrayBuffer, longTestBytesAsBuffer]);
+ const combinedByteArray = ethUtil.bufferToHex(combinedByteArrayBuffer);
+ const testUint256Offset = new BigNumber(prefixByteArrayBuffer.byteLength);
+ const bytes = await libBytes.publicReadBytes.callAsync(combinedByteArray, testUint256Offset);
+ return expect(bytes).to.be.equal(longData);
+ });
+
+ it('should fail if the byte array is too short to hold the length of a nested byte array', async () => {
+ // The length of the nested array is 32 bytes. By storing less than 32 bytes, a length cannot be read.
+ const offset = new BigNumber(0);
+ return expectRevertOrOtherErrorAsync(
+ libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, offset),
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED,
+ );
+ });
+
+ it('should fail if we store a nested byte array length, without a nested byte array', async () => {
+ const offset = new BigNumber(0);
+ return expectRevertOrOtherErrorAsync(
+ libBytes.publicReadBytes.callAsync(testBytes32, offset),
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED,
+ );
+ });
+
+ it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array', async () => {
+ const badOffset = new BigNumber(ethUtil.toBuffer(byteArrayShorterThan32Bytes).byteLength);
+ return expectRevertOrOtherErrorAsync(
+ libBytes.publicReadBytes.callAsync(byteArrayShorterThan32Bytes, badOffset),
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED,
+ );
+ });
+
+ it('should fail if the length between the offset and end of the byte array is too short to hold the nested byte array', async () => {
+ const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength);
+ return expectRevertOrOtherErrorAsync(
+ libBytes.publicReadBytes.callAsync(testBytes32, badOffset),
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_32_LENGTH_REQUIRED,
+ );
+ });
+ });
+
+ describe('writeBytes', () => {
+ it('should successfully write short, nested array of bytes when it takes up the whole array)', async () => {
+ const testBytesOffset = new BigNumber(0);
+ const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength));
+ const bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, testBytesOffset, shortData);
+ const bytesRead = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset);
+ return expect(bytesRead).to.be.equal(shortData);
+ });
+
+ it('should successfully write short, nested array of bytes when it is offset in the array', async () => {
+ // Write a prefix to the array
+ const prefixData = '0xabcdef';
+ const prefixDataAsBuffer = ethUtil.toBuffer(prefixData);
+ const prefixOffset = new BigNumber(0);
+ const emptyByteArray = ethUtil.bufferToHex(
+ new Buffer(prefixDataAsBuffer.byteLength + shortTestBytesAsBuffer.byteLength),
+ );
+ let bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, prefixOffset, prefixData);
+ // Write data after prefix
+ const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength);
+ bytesWritten = await libBytes.publicWriteBytes.callAsync(bytesWritten, testBytesOffset, shortData);
+ // Read data after prefix and validate
+ const bytes = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset);
+ return expect(bytes).to.be.equal(shortData);
+ });
+
+ it('should successfully write a nested array of bytes - one word in length - when it takes up the whole array', async () => {
+ const testBytesOffset = new BigNumber(0);
+ const emptyByteArray = ethUtil.bufferToHex(new Buffer(wordOfTestBytesAsBuffer.byteLength));
+ const bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, testBytesOffset, wordOfData);
+ const bytesRead = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset);
+ return expect(bytesRead).to.be.equal(wordOfData);
+ });
+
+ it('should successfully write a nested array of bytes - one word in length - when it is offset in the array', async () => {
+ // Write a prefix to the array
+ const prefixData = '0xabcdef';
+ const prefixDataAsBuffer = ethUtil.toBuffer(prefixData);
+ const prefixOffset = new BigNumber(0);
+ const emptyByteArray = ethUtil.bufferToHex(
+ new Buffer(prefixDataAsBuffer.byteLength + wordOfTestBytesAsBuffer.byteLength),
+ );
+ let bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, prefixOffset, prefixData);
+ // Write data after prefix
+ const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength);
+ bytesWritten = await libBytes.publicWriteBytes.callAsync(bytesWritten, testBytesOffset, wordOfData);
+ // Read data after prefix and validate
+ const bytes = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset);
+ return expect(bytes).to.be.equal(wordOfData);
+ });
+
+ it('should successfully write a long, nested bytes when it takes up the whole array', async () => {
+ const testBytesOffset = new BigNumber(0);
+ const emptyByteArray = ethUtil.bufferToHex(new Buffer(longTestBytesAsBuffer.byteLength));
+ const bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, testBytesOffset, longData);
+ const bytesRead = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset);
+ return expect(bytesRead).to.be.equal(longData);
+ });
+
+ it('should successfully write long, nested array of bytes when it is offset in the array', async () => {
+ // Write a prefix to the array
+ const prefixData = '0xabcdef';
+ const prefixDataAsBuffer = ethUtil.toBuffer(prefixData);
+ const prefixOffset = new BigNumber(0);
+ const emptyByteArray = ethUtil.bufferToHex(
+ new Buffer(prefixDataAsBuffer.byteLength + longTestBytesAsBuffer.byteLength),
+ );
+ let bytesWritten = await libBytes.publicWriteBytes.callAsync(emptyByteArray, prefixOffset, prefixData);
+ // Write data after prefix
+ const testBytesOffset = new BigNumber(prefixDataAsBuffer.byteLength);
+ bytesWritten = await libBytes.publicWriteBytes.callAsync(bytesWritten, testBytesOffset, longData);
+ // Read data after prefix and validate
+ const bytes = await libBytes.publicReadBytes.callAsync(bytesWritten, testBytesOffset);
+ return expect(bytes).to.be.equal(longData);
+ });
+
+ it('should fail if the byte array is too short to hold the length of a nested byte array', async () => {
+ const offset = new BigNumber(0);
+ const emptyByteArray = ethUtil.bufferToHex(new Buffer(1));
+ return expectRevertOrOtherErrorAsync(
+ libBytes.publicWriteBytes.callAsync(emptyByteArray, offset, longData),
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED,
+ );
+ });
+
+ it('should fail if the length between the offset and end of the byte array is too short to hold the length of a nested byte array)', async () => {
+ const emptyByteArray = ethUtil.bufferToHex(new Buffer(shortTestBytesAsBuffer.byteLength));
+ const badOffset = new BigNumber(ethUtil.toBuffer(shortTestBytesAsBuffer).byteLength);
+ return expectRevertOrOtherErrorAsync(
+ libBytes.publicWriteBytes.callAsync(emptyByteArray, badOffset, shortData),
+ constants.LIB_BYTES_GREATER_OR_EQUAL_TO_NESTED_BYTES_LENGTH_REQUIRED,
+ );
+ });
+ });
});
+// tslint:disable:max-file-line-count
diff --git a/packages/contracts/test/libraries/lib_mem.ts b/packages/contracts/test/libraries/lib_mem.ts
new file mode 100644
index 000000000..90d54edcb
--- /dev/null
+++ b/packages/contracts/test/libraries/lib_mem.ts
@@ -0,0 +1,190 @@
+import { BigNumber } from '@0xproject/utils';
+import * as chai from 'chai';
+
+import { TestLibMemContract } from '../../src/generated_contract_wrappers/test_lib_mem';
+import { artifacts } from '../../src/utils/artifacts';
+import { chaiSetup } from '../../src/utils/chai_setup';
+import { provider, txDefaults } from '../../src/utils/web3_wrapper';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+// BUG: Ideally we would use Buffer.from(memory).toString('hex')
+// https://github.com/Microsoft/TypeScript/issues/23155
+const toHex = (buf: Uint8Array): string => buf.reduce((a, v) => a + ('00' + v.toString(16)).slice(-2), '0x');
+
+const fromHex = (str: string): Uint8Array => Uint8Array.from(Buffer.from(str.slice(2), 'hex'));
+
+describe('LibMem', () => {
+ let testLibMem: TestLibMemContract;
+
+ before(async () => {
+ // Deploy TestLibMem
+ testLibMem = await TestLibMemContract.deployFrom0xArtifactAsync(artifacts.TestLibMem, provider, txDefaults);
+ });
+
+ describe('memCopy', () => {
+ // Create memory 0x000102...FF
+ const memSize = 256;
+ const memory = new Uint8Array(memSize).map((_, i) => i);
+ const memHex = toHex(memory);
+
+ // Reference implementation to test against
+ const refMemcpy = (mem: Uint8Array, dest: number, source: number, length: number): Uint8Array =>
+ Uint8Array.from(memory).copyWithin(dest, source, source + length);
+
+ // Test vectors: destination, source, length, job description
+ type Tests = Array<[number, number, number, string]>;
+
+ const test = (tests: Tests) =>
+ tests.forEach(([dest, source, length, job]) =>
+ it(job, async () => {
+ const expected = refMemcpy(memory, dest, source, length);
+ const resultStr = await testLibMem.testMemcpy.callAsync(
+ memHex,
+ new BigNumber(dest),
+ new BigNumber(source),
+ new BigNumber(length),
+ );
+ const result = fromHex(resultStr);
+ expect(result).to.deep.equal(expected);
+ }),
+ );
+
+ test([[0, 0, 0, 'copies zero bytes with overlap']]);
+
+ describe('copies forward', () =>
+ test([
+ [128, 0, 0, 'zero bytes'],
+ [128, 0, 1, 'one byte'],
+ [128, 0, 11, 'eleven bytes'],
+ [128, 0, 31, 'thirty-one bytes'],
+ [128, 0, 32, 'one word'],
+ [128, 0, 64, 'two words'],
+ [128, 0, 96, 'three words'],
+ [128, 0, 33, 'one word and one byte'],
+ [128, 0, 72, 'two words and eight bytes'],
+ [128, 0, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies forward within one word', () =>
+ test([
+ [16, 0, 0, 'zero bytes'],
+ [16, 0, 1, 'one byte'],
+ [16, 0, 11, 'eleven bytes'],
+ [16, 0, 16, 'sixteen bytes'],
+ ]));
+
+ describe('copies forward with one byte overlap', () =>
+ test([
+ [0, 0, 1, 'one byte'],
+ [10, 0, 11, 'eleven bytes'],
+ [30, 0, 31, 'thirty-one bytes'],
+ [31, 0, 32, 'one word'],
+ [32, 0, 33, 'one word and one byte'],
+ [71, 0, 72, 'two words and eight bytes'],
+ [99, 0, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies forward with thirty-one bytes overlap', () =>
+ test([
+ [0, 0, 31, 'thirty-one bytes'],
+ [1, 0, 32, 'one word'],
+ [2, 0, 33, 'one word and one byte'],
+ [41, 0, 72, 'two words and eight bytes'],
+ [69, 0, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies forward with one word overlap', () =>
+ test([
+ [0, 0, 32, 'one word'],
+ [1, 0, 33, 'one word and one byte'],
+ [41, 0, 72, 'two words and eight bytes'],
+ [69, 0, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies forward with one word and one byte overlap', () =>
+ test([
+ [0, 0, 33, 'one word and one byte'],
+ [40, 0, 72, 'two words and eight bytes'],
+ [68, 0, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies forward with two words overlap', () =>
+ test([
+ [0, 0, 64, 'two words'],
+ [8, 0, 72, 'two words and eight bytes'],
+ [36, 0, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies forward within one word and one byte overlap', () =>
+ test([[0, 0, 1, 'one byte'], [10, 0, 11, 'eleven bytes'], [15, 0, 16, 'sixteen bytes']]));
+
+ describe('copies backward', () =>
+ test([
+ [0, 128, 0, 'zero bytes'],
+ [0, 128, 1, 'one byte'],
+ [0, 128, 11, 'eleven bytes'],
+ [0, 128, 31, 'thirty-one bytes'],
+ [0, 128, 32, 'one word'],
+ [0, 128, 64, 'two words'],
+ [0, 128, 96, 'three words'],
+ [0, 128, 33, 'one word and one byte'],
+ [0, 128, 72, 'two words and eight bytes'],
+ [0, 128, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies backward within one word', () =>
+ test([
+ [0, 16, 0, 'zero bytes'],
+ [0, 16, 1, 'one byte'],
+ [0, 16, 11, 'eleven bytes'],
+ [0, 16, 16, 'sixteen bytes'],
+ ]));
+
+ describe('copies backward with one byte overlap', () =>
+ test([
+ [0, 0, 1, 'one byte'],
+ [0, 10, 11, 'eleven bytes'],
+ [0, 30, 31, 'thirty-one bytes'],
+ [0, 31, 32, 'one word'],
+ [0, 32, 33, 'one word and one byte'],
+ [0, 71, 72, 'two words and eight bytes'],
+ [0, 99, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies backward with thirty-one bytes overlap', () =>
+ test([
+ [0, 0, 31, 'thirty-one bytes'],
+ [0, 1, 32, 'one word'],
+ [0, 2, 33, 'one word and one byte'],
+ [0, 41, 72, 'two words and eight bytes'],
+ [0, 69, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies backward with one word overlap', () =>
+ test([
+ [0, 0, 32, 'one word'],
+ [0, 1, 33, 'one word and one byte'],
+ [0, 41, 72, 'two words and eight bytes'],
+ [0, 69, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies backward with one word and one byte overlap', () =>
+ test([
+ [0, 0, 33, 'one word and one byte'],
+ [0, 40, 72, 'two words and eight bytes'],
+ [0, 68, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies backward with two words overlap', () =>
+ test([
+ [0, 0, 64, 'two words'],
+ [0, 8, 72, 'two words and eight bytes'],
+ [0, 36, 100, 'three words and four bytes'],
+ ]));
+
+ describe('copies forward within one word and one byte overlap', () =>
+ test([[0, 0, 1, 'one byte'], [0, 10, 11, 'eleven bytes'], [0, 15, 16, 'sixteen bytes']]));
+ });
+});