aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/contracts/compiler.json1
-rw-r--r--packages/contracts/package.json2
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol201
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol325
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetData.sol12
-rw-r--r--packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol2
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol48
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol14
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol3
-rw-r--r--packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol5
-rw-r--r--packages/contracts/src/utils/artifacts.ts2
-rw-r--r--packages/contracts/src/utils/assertions.ts41
-rw-r--r--packages/contracts/src/utils/constants.ts1
-rw-r--r--packages/contracts/src/utils/core_combinatorial_utils.ts4
-rw-r--r--packages/contracts/src/utils/exchange_wrapper.ts16
-rw-r--r--packages/contracts/test/asset_proxy/proxies.ts204
-rw-r--r--packages/contracts/test/exchange/core.ts6
-rw-r--r--packages/contracts/test/exchange/dispatcher.ts161
-rw-r--r--packages/contracts/test/exchange/match_orders.ts30
-rw-r--r--packages/contracts/test/exchange/transactions.ts4
-rw-r--r--packages/contracts/test/exchange/wrapper.ts6
-rw-r--r--packages/types/src/index.ts3
-rw-r--r--packages/website/ts/index.tsx2
-rw-r--r--packages/website/ts/utils/configs.ts2
24 files changed, 507 insertions, 588 deletions
diff --git a/packages/contracts/compiler.json b/packages/contracts/compiler.json
index 1ee58081a..56c8b1761 100644
--- a/packages/contracts/compiler.json
+++ b/packages/contracts/compiler.json
@@ -29,6 +29,7 @@
"Exchange",
"ExchangeWrapper",
"IAssetData",
+ "IAssetProxy",
"IValidator",
"IWallet",
"MixinAuthorizable",
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index b5a599fe5..1a26f3364 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -35,7 +35,7 @@
},
"config": {
"abis":
- "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|ExchangeWrapper|IAssetData|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyOwner|TestAssetProxyDispatcher|TestLibBytes|TestLibs|TestSignatureValidator|TestValidator|TestWallet|TokenRegistry|Whitelist|WETH9|ZRXToken).json"
+ "../migrations/artifacts/2.0.0/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|TestAssetProxyOwner|TestAssetProxyDispatcher|TestLibBytes|TestLibs|TestSignatureValidator|TestValidator|TestWallet|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 b4780b52b..aed62f54f 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol
@@ -20,138 +20,103 @@ pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "../../utils/LibBytes/LibBytes.sol";
-import "./interfaces/IAssetProxy.sol";
import "./MixinAuthorizable.sol";
contract ERC20Proxy is
- IAssetProxy,
MixinAuthorizable
{
// Id of this proxy.
bytes4 constant PROXY_ID = bytes4(keccak256("ERC20Token(address)"));
- /// @dev Internal version of `transferFrom`.
- /// @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 assetData,
- address from,
- address to,
- uint256 amount
- )
+ function ()
external
{
- require(
- authorized[msg.sender],
- "SENDER_NOT_AUTHORIZED"
- );
-
- // `transferFrom`.
- // The function is marked `external`, so no abi decodeding is done for
- // us. Instead, we expect the `calldata` memory to contain the
- // following:
- //
- // | Area | Offset | Length | Contents |
- // |----------|--------|---------|-------------------------------------|
- // | Header | 0 | 4 | function selector |
- // | Params | | 4 * 32 | function parameters: |
- // | | 4 | | 1. offset to assetData (*) |
- // | | 36 | | 2. from |
- // | | 68 | | 3. to |
- // | | 100 | | 4. amount |
- // | Data | | | assetData: |
- // | | 132 | 32 | assetData Length |
- // | | 164 | ** | assetData Contents |
- //
- // (*): offset is computed from start of function parameters, so offset
- // by an additional 4 bytes in the calldata.
- //
- // WARNING: The ABIv2 specification allows additional padding between
- // the Params and Data section. This will result in a larger
- // offset to assetData.
-
- // Asset data itself is encoded as follows:
- //
- // | Area | Offset | Length | Contents |
- // |----------|--------|---------|-------------------------------------|
- // | Header | 0 | 4 | function selector |
- // | Params | | 1 * 32 | function parameters: |
- // | | 4 | 12 + 20 | 1. token address |
-
- // Transfer tokens.
- // We do a raw call so we can check the success separate
- // from the return data.
- // We construct calldata for the `token.transferFrom` ABI.
- // The layout of this calldata is in the table below.
- //
- // | Area | Offset | Length | Contents |
- // |----------|--------|---------|-------------------------------------|
- // | Header | 0 | 4 | function selector |
- // | Params | | 3 * 32 | function parameters: |
- // | | 4 | | 1. from |
- // | | 36 | | 2. to |
- // | | 68 | | 3. amount |
-
assembly {
- /////// Token contract address ///////
- // The token address is found as follows:
- // * It is stored at offset 4 in `assetData` contents.
- // * This is stored at offset 32 from `assetData`.
- // * The offset to `assetData` from Params is stored at offset
- // 4 in calldata.
- // * The offset of Params in calldata is 4.
- // So we read location 4 and add 32 + 4 + 4 to it.
- let token := calldataload(add(calldataload(4), 40))
-
- /////// Setup Header Area ///////
- // This area holds the 4-byte `transferFrom` selector.
- // Any trailing data in transferFromSelector will be
- // overwritten in the next `mstore` call.
- mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
-
- /////// Setup Params Area ///////
- // We copy the fields `from`, `to` and `amount` in bulk
- // from our own calldata to the new calldata.
- calldatacopy(4, 36, 96)
+ // The first 4 bytes of calldata holds the function selector
+ let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
+
+ // `transferFrom` will be called with the following parameters:
+ // assetData Encoded byte array.
+ // from Address to transfer asset from.
+ // to Address to transfer asset to.
+ // amount Amount of asset to transfer.
+ // bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
+ if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
- /////// Call `token.transferFrom` using the calldata ///////
- let success := call(
- gas, // forward all gas
- token, // call address of token contract
- 0, // don't send any ETH
- 0, // pointer to start of input
- 100, // length of input
- 0, // write output over input
- 32 // output size should be 32 bytes
- )
+ // To lookup a value in a mapping, we load from the storage location keccak256(k, p),
+ // where k is the key left padded to 32 bytes and p is the storage slot
+ let start := mload(64)
+ mstore(start, and(caller, 0xffffffffffffffffffffffffffffffffffffffff))
+ mstore(add(start, 32), authorized_slot)
- /////// Check return data. ///////
- // If there is no return data, we assume the token incorrectly
- // does not return a bool. In this case we expect it to revert
- // on failure, which was handled above.
- // If the token does return data, we require that it is a single
- // nonzero 32 bytes value.
- // So the transfer succeeded if the call succeeded and either
- // returned nothing, or returned a non-zero 32 byte value.
- success := and(success, or(
- iszero(returndatasize),
- and(
- eq(returndatasize, 32),
- gt(mload(0), 0)
+ // Revert if authorized[msg.sender] == false
+ if iszero(sload(keccak256(start, 64))) {
+ // Revert with `Error("SENDER_NOT_AUTHORIZED")`
+ mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
+ mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
+ mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
+ mstore(96, 0)
+ revert(0, 100)
+ }
+
+ /////// Token contract address ///////
+ // The token address is found as follows:
+ // * It is stored at offset 4 in `assetData` contents.
+ // * This is stored at offset 32 from `assetData`.
+ // * The offset to `assetData` from Params is stored at offset
+ // 4 in calldata.
+ // * The offset of Params in calldata is 4.
+ // So we read location 4 and add 32 + 4 + 4 to it.
+ let token := calldataload(add(calldataload(4), 40))
+
+ /////// Setup Header Area ///////
+ // This area holds the 4-byte `transferFrom` selector.
+ // Any trailing data in transferFromSelector will be
+ // overwritten in the next `mstore` call.
+ mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
+
+ /////// Setup Params Area ///////
+ // We copy the fields `from`, `to` and `amount` in bulk
+ // from our own calldata to the new calldata.
+ calldatacopy(4, 36, 96)
+
+ /////// Call `token.transferFrom` using the calldata ///////
+ let success := call(
+ gas, // forward all gas
+ token, // call address of token contract
+ 0, // don't send any ETH
+ 0, // pointer to start of input
+ 100, // length of input
+ 0, // write output over input
+ 32 // output size should be 32 bytes
)
- ))
- if success {
- return(0, 0)
+
+ /////// Check return data. ///////
+ // If there is no return data, we assume the token incorrectly
+ // does not return a bool. In this case we expect it to revert
+ // on failure, which was handled above.
+ // If the token does return data, we require that it is a single
+ // nonzero 32 bytes value.
+ // So the transfer succeeded if the call succeeded and either
+ // returned nothing, or returned a non-zero 32 byte value.
+ success := and(success, or(
+ iszero(returndatasize),
+ and(
+ eq(returndatasize, 32),
+ gt(mload(0), 0)
+ )
+ ))
+ if success {
+ return(0, 0)
+ }
+
+ // Revert with `Error("TRANSFER_FAILED")`
+ mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
+ mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
+ mstore(64, 0x0000000f5452414e534645525f4641494c454400000000000000000000000000)
+ mstore(96, 0)
+ revert(0, 100)
}
-
- // Revert with `Error("TRANSFER_FAILED")`
- mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
- mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
- mstore(64, 0x0000000f5452414e534645525f4641494c454400000000000000000000000000)
- mstore(96, 0)
- revert(0, 100)
}
}
@@ -159,7 +124,7 @@ contract ERC20Proxy is
/// @return Proxy id.
function getProxyId()
external
- view
+ pure
returns (bytes4)
{
return PROXY_ID;
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
index 8d7cea717..b73dc36cc 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol
@@ -20,178 +20,189 @@ pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "../../utils/LibBytes/LibBytes.sol";
-import "./interfaces/IAssetProxy.sol";
import "./MixinAuthorizable.sol";
contract ERC721Proxy is
- IAssetProxy,
MixinAuthorizable
{
// Id of this proxy.
bytes4 constant PROXY_ID = bytes4(keccak256("ERC721Token(address,uint256,bytes)"));
- /// @dev Internal version of `transferFrom`.
- /// @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 assetData,
- address from,
- address to,
- uint256 amount
- )
+ function ()
external
{
- require(
- authorized[msg.sender],
- "SENDER_NOT_AUTHORIZED"
- );
-
- // `transferFrom`.
- // The function is marked `external`, so no abi decodeding is done for
- // us. Instead, we expect the `calldata` memory to contain the
- // following:
- //
- // | Area | Offset | Length | Contents |
- // |----------|--------|---------|-------------------------------------|
- // | Header | 0 | 4 | function selector |
- // | Params | | 4 * 32 | function parameters: |
- // | | 4 | | 1. offset to assetData (*) |
- // | | 36 | | 2. from |
- // | | 68 | | 3. to |
- // | | 100 | | 4. amount |
- // | Data | | | assetData: |
- // | | 132 | 32 | assetData Length |
- // | | 164 | ** | assetData Contents |
- //
- // (*): offset is computed from start of function parameters, so offset
- // by an additional 4 bytes in the calldata.
- //
- // WARNING: The ABIv2 specification allows additional padding between
- // the Params and Data section. This will result in a larger
- // offset to assetData.
-
- // Asset data itself is encoded as follows:
- //
- // | Area | Offset | Length | Contents |
- // |----------|--------|---------|-------------------------------------|
- // | Header | 0 | 4 | function selector |
- // | Params | | 3 * 32 | function parameters: |
- // | | 4 | 12 + 20 | 1. token address |
- // | | 36 | | 2. tokenId |
- // | | 68 | | 3. offset to receiverData (*) |
- // | Data | | | receiverData: |
- // | | 100 | 32 | receiverData Length |
- // | | 132 | ** | receiverData Contents |
-
- // We construct calldata for the `token.safeTransferFrom` ABI.
- // The layout of this calldata is in the table below.
- //
- // | Area | Offset | Length | Contents |
- // |----------|--------|---------|-------------------------------------|
- // | Header | 0 | 4 | function selector |
- // | Params | | 4 * 32 | function parameters: |
- // | | 4 | | 1. from |
- // | | 36 | | 2. to |
- // | | 68 | | 3. tokenId |
- // | | 100 | | 4. offset to receiverData (*) |
- // | Data | | | receiverData: |
- // | | 132 | 32 | receiverData Length |
- // | | 164 | ** | receiverData Contents |
-
assembly {
- // There exists only 1 of each token.
- // require(amount == 1, "INVALID_AMOUNT")
- if sub(calldataload(100), 1) {
- // Revert with `Error("INVALID_AMOUNT")`
+ // The first 4 bytes of calldata holds the function selector
+ let selector := and(calldataload(0), 0xffffffff00000000000000000000000000000000000000000000000000000000)
+
+ // `transferFrom` will be called with the following parameters:
+ // assetData Encoded byte array.
+ // from Address to transfer asset from.
+ // to Address to transfer asset to.
+ // amount Amount of asset to transfer.
+ // bytes4(keccak256("transferFrom(bytes,address,address,uint256)")) = 0xa85e59e4
+ if eq(selector, 0xa85e59e400000000000000000000000000000000000000000000000000000000) {
+
+ // To lookup a value in a mapping, we load from the storage location keccak256(k, p),
+ // where k is the key left padded to 32 bytes and p is the storage slot
+ let start := mload(64)
+ mstore(start, and(caller, 0xffffffffffffffffffffffffffffffffffffffff))
+ mstore(add(start, 32), authorized_slot)
+
+ // Revert if authorized[msg.sender] == false
+ if iszero(sload(keccak256(start, 64))) {
+ // Revert with `Error("SENDER_NOT_AUTHORIZED")`
+ mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
+ mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
+ mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
+ mstore(96, 0)
+ revert(0, 100)
+ }
+
+ // `transferFrom`.
+ // The function is marked `external`, so no abi decodeding is done for
+ // us. Instead, we expect the `calldata` memory to contain the
+ // following:
+ //
+ // | Area | Offset | Length | Contents |
+ // |----------|--------|---------|-------------------------------------|
+ // | Header | 0 | 4 | function selector |
+ // | Params | | 4 * 32 | function parameters: |
+ // | | 4 | | 1. offset to assetData (*) |
+ // | | 36 | | 2. from |
+ // | | 68 | | 3. to |
+ // | | 100 | | 4. amount |
+ // | Data | | | assetData: |
+ // | | 132 | 32 | assetData Length |
+ // | | 164 | ** | assetData Contents |
+ //
+ // (*): offset is computed from start of function parameters, so offset
+ // by an additional 4 bytes in the calldata.
+ //
+ // WARNING: The ABIv2 specification allows additional padding between
+ // the Params and Data section. This will result in a larger
+ // offset to assetData.
+
+ // Asset data itself is encoded as follows:
+ //
+ // | Area | Offset | Length | Contents |
+ // |----------|--------|---------|-------------------------------------|
+ // | Header | 0 | 4 | function selector |
+ // | Params | | 3 * 32 | function parameters: |
+ // | | 4 | 12 + 20 | 1. token address |
+ // | | 36 | | 2. tokenId |
+ // | | 68 | | 3. offset to receiverData (*) |
+ // | Data | | | receiverData: |
+ // | | 100 | 32 | receiverData Length |
+ // | | 132 | ** | receiverData Contents |
+
+ // We construct calldata for the `token.safeTransferFrom` ABI.
+ // The layout of this calldata is in the table below.
+ //
+ // | Area | Offset | Length | Contents |
+ // |----------|--------|---------|-------------------------------------|
+ // | Header | 0 | 4 | function selector |
+ // | Params | | 4 * 32 | function parameters: |
+ // | | 4 | | 1. from |
+ // | | 36 | | 2. to |
+ // | | 68 | | 3. tokenId |
+ // | | 100 | | 4. offset to receiverData (*) |
+ // | Data | | | receiverData: |
+ // | | 132 | 32 | receiverData Length |
+ // | | 164 | ** | receiverData Contents |
+
+ // There exists only 1 of each token.
+ // require(amount == 1, "INVALID_AMOUNT")
+ if sub(calldataload(100), 1) {
+ // Revert with `Error("INVALID_AMOUNT")`
+ mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
+ mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
+ mstore(64, 0x0000000e494e56414c49445f414d4f554e540000000000000000000000000000)
+ mstore(96, 0)
+ revert(0, 100)
+ }
+
+ // Require assetData to be at least 132 bytes
+ let offset := calldataload(4)
+ if lt(calldataload(add(offset, 4)), 132) {
+ // Revert with `Error("LENGTH_GREATER_THAN_131_REQUIRED")`
+ mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
+ mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
+ mstore(64, 0x000000204c454e4754485f475245415445525f5448414e5f3133315f52455155)
+ mstore(96, 0x4952454400000000000000000000000000000000000000000000000000000000)
+ revert(0, 100)
+ }
+
+ /////// Setup State ///////
+ // `cdStart` is the start of the calldata for
+ // `token.safeTransferFrom` (equal to free memory ptr).
+ let cdStart := mload(64)
+ // `dataAreaLength` is the total number of words
+ // needed to store `receiverData`
+ // As-per the ABI spec, this value is padded up to
+ // the nearest multiple of 32,
+ // and includes 32-bytes for length.
+ // It's calculated as folows:
+ // - Unpadded length in bytes = `mload(receiverData) + 32`
+ // - Add 31 to convert rounding down to rounding up.
+ // Combined with the previous and this is `63`.
+ // - Round down to nearest multiple of 32 by clearing
+ // bits 0x1F. This is done with `and` and a mask.
+
+ /////// Setup Header Area ///////
+ // This area holds the 4-byte `transferFromSelector`.
+ // Any trailing data in transferFromSelector will be
+ // overwritten in the next `mstore` call.
+ mstore(cdStart, 0xb88d4fde00000000000000000000000000000000000000000000000000000000)
+
+ /////// Setup Params Area ///////
+ // Each parameter is padded to 32-bytes.
+ // The entire Params Area is 128 bytes.
+ // Notes:
+ // 1. A 20-byte mask is applied to addresses
+ // to zero-out the unused bytes.
+ // 2. The offset to `receiverData` is the length
+ // of the Params Area (128 bytes).
+
+ let length := calldataload(add(offset, 136))
+ let token := calldataload(add(offset, 40))
+
+ // Round length up to multiple of 32
+ length := and(add(length, 31), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0)
+
+ // Copy `from` and `to`
+ calldatacopy(add(cdStart, 4), 36, 64)
+
+ // TokenId
+ mstore(add(cdStart, 68), calldataload(add(offset, 72)))
+
+ // Offset to receiverData
+ mstore(add(cdStart, 100), 128)
+
+ // receiverData (including length)
+ calldatacopy(add(cdStart, 132), add(offset, 136), add(length, 32))
+
+ /////// Call `token.safeTransferFrom` using the calldata ///////
+ let success := call(
+ gas, // forward all gas
+ token, // call address of token contract
+ 0, // don't send any ETH
+ cdStart, // pointer to start of input
+ add(length, 164), // length of input
+ 0, // write output to null
+ 0 // output size is 0 bytes
+ )
+ if success {
+ return(0, 0)
+ }
+
+ // Revert with `Error("TRANSFER_FAILED")`
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
- mstore(64, 0x0000000e494e56414c49445f414d4f554e540000000000000000000000000000)
+ mstore(64, 0x0000000f5452414e534645525f4641494c454400000000000000000000000000)
mstore(96, 0)
revert(0, 100)
}
-
- // Require assetData to be at least 132 bytes
- let offset := calldataload(4)
- if lt(calldataload(add(offset, 4)), 132) {
- // Revert with `Error("LENGTH_GREATER_THAN_131_REQUIRED")`
- mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
- mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
- mstore(64, 0x000000204c454e4754485f475245415445525f5448414e5f3133315f52455155)
- mstore(96, 0x4952454400000000000000000000000000000000000000000000000000000000)
- revert(0, 100)
- }
-
- /////// Setup State ///////
- // `cdStart` is the start of the calldata for
- // `token.safeTransferFrom` (equal to free memory ptr).
- let cdStart := mload(64)
- // `dataAreaLength` is the total number of words
- // needed to store `receiverData`
- // As-per the ABI spec, this value is padded up to
- // the nearest multiple of 32,
- // and includes 32-bytes for length.
- // It's calculated as folows:
- // - Unpadded length in bytes = `mload(receiverData) + 32`
- // - Add 31 to convert rounding down to rounding up.
- // Combined with the previous and this is `63`.
- // - Round down to nearest multiple of 32 by clearing
- // bits 0x1F. This is done with `and` and a mask.
-
- /////// Setup Header Area ///////
- // This area holds the 4-byte `transferFromSelector`.
- // Any trailing data in transferFromSelector will be
- // overwritten in the next `mstore` call.
- mstore(cdStart, 0xb88d4fde00000000000000000000000000000000000000000000000000000000)
-
- /////// Setup Params Area ///////
- // Each parameter is padded to 32-bytes.
- // The entire Params Area is 128 bytes.
- // Notes:
- // 1. A 20-byte mask is applied to addresses
- // to zero-out the unused bytes.
- // 2. The offset to `receiverData` is the length
- // of the Params Area (128 bytes).
-
- let length := calldataload(add(offset, 136))
- let token := calldataload(add(offset, 40))
-
- // Round length up to multiple of 32
- length := and(add(length, 31), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0)
-
- // Copy `from` and `to`
- calldatacopy(add(cdStart, 4), 36, 64)
-
- // TokenId
- mstore(add(cdStart, 68), calldataload(add(offset, 72)))
-
- // Offset to receiverData
- mstore(add(cdStart, 100), 128)
-
- // receiverData (including length)
- calldatacopy(add(cdStart, 132), add(offset, 136), add(length, 32))
-
- /////// Call `token.safeTransferFrom` using the calldata ///////
- let success := call(
- gas, // forward all gas
- token, // call address of token contract
- 0, // don't send any ETH
- cdStart, // pointer to start of input
- add(length, 164), // length of input
- 0, // write output to null
- 0 // output size is 0 bytes
- )
- if success {
- return(0, 0)
- }
-
- // Revert with `Error("TRANSFER_FAILED")`
- mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
- mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
- mstore(64, 0x0000000f5452414e534645525f4641494c454400000000000000000000000000)
- mstore(96, 0)
- revert(0, 100)
}
}
@@ -199,7 +210,7 @@ contract ERC721Proxy is
/// @return Proxy id.
function getProxyId()
external
- view
+ pure
returns (bytes4)
{
return PROXY_ID;
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetData.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetData.sol
index 8c78ee8c4..7ebd6acf0 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetData.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetData.sol
@@ -23,14 +23,16 @@ pragma solidity ^0.4.23;
// This argument is ABI encoded as one of the methods of this interface.
interface IAssetData {
- function ERC20Token(
- address tokenContract)
- external pure;
+ function ERC20Token(address tokenContract)
+ external
+ pure;
function ERC721Token(
address tokenContract,
uint256 tokenId,
- bytes receiverData)
- external pure;
+ bytes receiverData
+ )
+ external
+ pure;
}
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 ae8e195da..eacd5a412 100644
--- a/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol
+++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/interfaces/IAssetProxy.sol
@@ -42,6 +42,6 @@ contract IAssetProxy is
/// @return Proxy id.
function getProxyId()
external
- view
+ pure
returns (bytes4);
}
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
index f7086f543..9e9d88ce7 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinAssetProxyDispatcher.sol
@@ -32,43 +32,28 @@ contract MixinAssetProxyDispatcher is
// Mapping from Asset Proxy Id's to their respective Asset Proxy
mapping (bytes4 => IAssetProxy) public assetProxies;
- /// @dev Registers an asset proxy to an asset proxy id.
- /// An id can only be assigned to a single proxy at a given time.
- /// @param assetProxyId Id to register`newAssetProxy` under.
- /// @param newAssetProxy Address of new asset proxy to register, or 0x0 to unset assetProxyId.
- /// @param oldAssetProxy Existing asset proxy to overwrite, or 0x0 if assetProxyId is currently unused.
- function registerAssetProxy(
- bytes4 assetProxyId,
- address newAssetProxy,
- address oldAssetProxy
- )
+ /// @dev Registers an asset proxy to its asset proxy id.
+ /// Once an asset proxy is registered, it cannot be unregistered.
+ /// @param assetProxy Address of new asset proxy to register.
+ function registerAssetProxy(address assetProxy)
external
onlyOwner
{
- // Ensure the existing asset proxy is not unintentionally overwritten
+ IAssetProxy assetProxyContract = IAssetProxy(assetProxy);
+
+ // Ensure that no asset proxy exists with current id.
+ bytes4 assetProxyId = assetProxyContract.getProxyId();
address currentAssetProxy = assetProxies[assetProxyId];
require(
- oldAssetProxy == currentAssetProxy,
- "ASSET_PROXY_MISMATCH"
+ currentAssetProxy == address(0),
+ "ASSET_PROXY_ALREADY_EXISTS"
);
- IAssetProxy assetProxy = IAssetProxy(newAssetProxy);
-
- // Ensure that the id of newAssetProxy matches the passed in assetProxyId, unless it is being reset to 0.
- if (newAssetProxy != address(0)) {
- bytes4 newAssetProxyId = assetProxy.getProxyId();
- require(
- newAssetProxyId == assetProxyId,
- "ASSET_PROXY_ID_MISMATCH"
- );
- }
-
// Add asset proxy and log registration.
- assetProxies[assetProxyId] = assetProxy;
- emit AssetProxySet(
+ assetProxies[assetProxyId] = assetProxyContract;
+ emit AssetProxyRegistered(
assetProxyId,
- newAssetProxy,
- oldAssetProxy
+ assetProxy
);
}
@@ -112,7 +97,7 @@ contract MixinAssetProxyDispatcher is
0xFFFFFFFF00000000000000000000000000000000000000000000000000000000
)
}
- IAssetProxy assetProxy = assetProxies[assetProxyId];
+ address assetProxy = assetProxies[assetProxyId];
// Ensure that assetProxy exists
require(
@@ -135,7 +120,6 @@ contract MixinAssetProxyDispatcher is
// | | 132 | 32 | assetData Length |
// | | 164 | ** | assetData Contents |
- bool success;
assembly {
/////// Setup State ///////
// `cdStart` is the start of the calldata for `assetProxy.transferFrom` (equal to free memory ptr).
@@ -173,7 +157,7 @@ contract MixinAssetProxyDispatcher is
}
/////// Call `assetProxy.transferFrom` using the constructed calldata ///////
- success := call(
+ let success := call(
gas, // forward all gas
assetProxy, // call address of asset proxy
0, // don't send any ETH
@@ -182,7 +166,7 @@ contract MixinAssetProxyDispatcher is
cdStart, // write output over input
512 // reserve 512 bytes for output
)
- if eq(success, 0) {
+ if iszero(success) {
revert(cdStart, returndatasize())
}
}
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 fa55dff00..66f3b5796 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IAssetProxyDispatcher.sol
@@ -20,16 +20,10 @@ pragma solidity ^0.4.24;
contract IAssetProxyDispatcher {
- /// @dev Registers an asset proxy to an asset proxy id.
- /// An id can only be assigned to a single proxy at a given time.
- /// @param assetProxyId Id to register`newAssetProxy` under.
- /// @param newAssetProxy Address of new asset proxy to register, or 0x0 to unset assetProxyId.
- /// @param oldAssetProxy Existing asset proxy to overwrite, or 0x0 if assetProxyId is currently unused.
- function registerAssetProxy(
- bytes4 assetProxyId,
- address newAssetProxy,
- address oldAssetProxy
- )
+ /// @dev Registers an asset proxy to its asset proxy id.
+ /// Once an asset proxy is registered, it cannot be unregistered.
+ /// @param assetProxy Address of new asset proxy to register.
+ function registerAssetProxy(address assetProxy)
external;
/// @dev Gets an asset proxy.
diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol
index e37f41ada..01aa78a1d 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol
@@ -54,8 +54,7 @@ contract LibExchangeErrors {
string constant FAILED_EXECUTION = "FAILED_EXECUTION"; // Transaction execution failed.
/// registerAssetProxy errors ///
- string constant ASSET_PROXY_MISMATCH = "ASSET_PROXY_MISMATCH"; // oldAssetProxy proxy does not match currentAssetProxy.
- string constant ASSET_PROXY_ID_MISMATCH = "ASSET_PROXY_ID_MISMATCH"; // newAssetProxyId does not match given assetProxyId.
+ string constant ASSET_PROXY_ALREADY_EXISTS = "ASSET_PROXY_ALREADY_EXISTS"; // AssetProxy with same id already exists.
/// dispatchTransferFrom errors ///
string constant ASSET_PROXY_DOES_NOT_EXIST = "ASSET_PROXY_DOES_NOT_EXIST"; // No assetProxy registered at given id.
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 c2b506dcf..5bf59c6ce 100644
--- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
+++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MAssetProxyDispatcher.sol
@@ -26,10 +26,9 @@ contract MAssetProxyDispatcher is
{
// Logs registration of new asset proxy
- event AssetProxySet(
+ event AssetProxyRegistered(
bytes4 id, // Id of new registered AssetProxy.
- address newAssetProxy, // Address of new registered AssetProxy.
- address oldAssetProxy // Address of AssetProxy that was overwritten at given id (or null address).
+ address assetProxy // Address of new registered AssetProxy.
);
/// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts
index d58e7973c..b25266409 100644
--- a/packages/contracts/src/utils/artifacts.ts
+++ b/packages/contracts/src/utils/artifacts.ts
@@ -8,6 +8,7 @@ import * as ERC20Proxy from '../artifacts/ERC20Proxy.json';
import * as ERC721Proxy from '../artifacts/ERC721Proxy.json';
import * as Exchange from '../artifacts/Exchange.json';
import * as ExchangeWrapper from '../artifacts/ExchangeWrapper.json';
+import * as IAssetProxy from '../artifacts/IAssetProxy.json';
import * as MixinAuthorizable from '../artifacts/MixinAuthorizable.json';
import * as MultiSigWallet from '../artifacts/MultiSigWallet.json';
import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json';
@@ -33,6 +34,7 @@ export const artifacts = {
Exchange: (Exchange as any) as ContractArtifact,
ExchangeWrapper: (ExchangeWrapper as any) as ContractArtifact,
EtherToken: (EtherToken as any) as ContractArtifact,
+ IAssetProxy: (IAssetProxy as any) as ContractArtifact,
MixinAuthorizable: (MixinAuthorizable as any) as ContractArtifact,
MultiSigWallet: (MultiSigWallet as any) as ContractArtifact,
MultiSigWalletWithTimeLock: (MultiSigWalletWithTimeLock as any) as ContractArtifact,
diff --git a/packages/contracts/src/utils/assertions.ts b/packages/contracts/src/utils/assertions.ts
index e702a3200..baba892d3 100644
--- a/packages/contracts/src/utils/assertions.ts
+++ b/packages/contracts/src/utils/assertions.ts
@@ -1,8 +1,10 @@
import { RevertReason } from '@0xproject/types';
import * as chai from 'chai';
+import { TransactionReceipt, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash';
import { constants } from './constants';
+import { web3Wrapper } from './web3_wrapper';
const expect = chai.expect;
@@ -53,18 +55,45 @@ export function expectRevertOrAlwaysFailingTransactionAsync<T>(p: Promise<T>): P
}
/**
- * Rejects if the given Promise does not reject with the given revert reason or "always
- * failing transaction" error.
+ * Rejects if at least one the following conditions is not met:
+ * 1) The given Promise rejects with the given revert reason.
+ * 2) The given Promise rejects with an error containing "always failing transaction"
+ * 3) The given Promise fulfills with a txReceipt that has a status of 0 or '0', indicating the transaction failed.
+ * 4) The given Promise fulfills with a txHash and corresponding txReceipt has a status of 0 or '0'.
* @param p the Promise which is expected to reject
* @param reason a specific revert reason
* @returns a new Promise which will reject if the conditions are not met and
* otherwise resolve with no value.
*/
-export function expectRevertReasonOrAlwaysFailingTransactionAsync<T>(
- p: Promise<T>,
+export async function expectRevertReasonOrAlwaysFailingTransactionAsync(
+ p: Promise<string | TransactionReceiptWithDecodedLogs | TransactionReceipt>,
reason: RevertReason,
-): PromiseLike<void> {
- return _expectEitherErrorAsync(p, 'always failing transaction', reason);
+): Promise<void> {
+ return p
+ .then(async result => {
+ let txReceiptStatus: string | 0 | 1 | null;
+ if (typeof result === 'string') {
+ // Result is a txHash. We need to make a web3 call to get the receipt.
+ const txReceipt = await web3Wrapper.awaitTransactionMinedAsync(result);
+ txReceiptStatus = txReceipt.status;
+ } else if ('status' in result) {
+ // Result is a TransactionReceiptWithDecodedLogs or TransactionReceipt
+ // and status is a field of result.
+ txReceiptStatus = result.status;
+ } else {
+ throw new Error('Unexpected result type');
+ }
+ expect(_.toString(txReceiptStatus)).to.equal(
+ '0',
+ 'transactionReceipt had a non-zero status, indicating success',
+ );
+ })
+ .catch(err => {
+ expect(err.message).to.satisfy(
+ (msg: string) => _.includes(msg, reason) || _.includes(msg, 'always failing transaction'),
+ `Expected ${reason} or 'always failing transaction' but error message was ${err.message}`,
+ );
+ });
}
/**
diff --git a/packages/contracts/src/utils/constants.ts b/packages/contracts/src/utils/constants.ts
index 2b2bd2425..8e68f376d 100644
--- a/packages/contracts/src/utils/constants.ts
+++ b/packages/contracts/src/utils/constants.ts
@@ -27,6 +27,7 @@ export const constants = {
MAX_ETHERTOKEN_WITHDRAW_GAS: 43000,
MAX_TOKEN_TRANSFERFROM_GAS: 80000,
MAX_TOKEN_APPROVE_GAS: 60000,
+ TRANSFER_FROM_GAS: 150000,
DUMMY_TOKEN_NAME: '',
DUMMY_TOKEN_SYMBOL: '',
DUMMY_TOKEN_DECIMALS: new BigNumber(18),
diff --git a/packages/contracts/src/utils/core_combinatorial_utils.ts b/packages/contracts/src/utils/core_combinatorial_utils.ts
index 5b725fbe3..93f4fc79d 100644
--- a/packages/contracts/src/utils/core_combinatorial_utils.ts
+++ b/packages/contracts/src/utils/core_combinatorial_utils.ts
@@ -96,8 +96,8 @@ export async function coreCombinatorialUtilsFactoryAsync(
zrxAssetData,
);
const exchangeWrapper = new ExchangeWrapper(exchangeContract, provider);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, ownerAddress);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC721, erc721Proxy.address, ownerAddress);
+ await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, ownerAddress);
+ await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, ownerAddress);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeContract.address, {
diff --git a/packages/contracts/src/utils/exchange_wrapper.ts b/packages/contracts/src/utils/exchange_wrapper.ts
index ad68c8ff4..baf967065 100644
--- a/packages/contracts/src/utils/exchange_wrapper.ts
+++ b/packages/contracts/src/utils/exchange_wrapper.ts
@@ -1,12 +1,10 @@
-import { AssetProxyId, SignedOrder } from '@0xproject/types';
+import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
-import * as _ from 'lodash';
import { ExchangeContract } from '../generated_contract_wrappers/exchange';
-import { constants } from './constants';
import { formatters } from './formatters';
import { LogDecoder } from './log_decoder';
import { orderUtils } from './order_utils';
@@ -192,20 +190,10 @@ export class ExchangeWrapper {
return tx;
}
public async registerAssetProxyAsync(
- assetProxyId: AssetProxyId,
assetProxyAddress: string,
from: string,
- opts: { oldAssetProxyAddressIfExists?: string } = {},
): Promise<TransactionReceiptWithDecodedLogs> {
- const oldAssetProxyAddress = _.isUndefined(opts.oldAssetProxyAddressIfExists)
- ? constants.NULL_ADDRESS
- : opts.oldAssetProxyAddressIfExists;
- const txHash = await this._exchange.registerAssetProxy.sendTransactionAsync(
- assetProxyId,
- assetProxyAddress,
- oldAssetProxyAddress,
- { from },
- );
+ const txHash = await this._exchange.registerAssetProxy.sendTransactionAsync(assetProxyAddress, { from });
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx;
}
diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts
index 39121d95c..08026331f 100644
--- a/packages/contracts/test/asset_proxy/proxies.ts
+++ b/packages/contracts/test/asset_proxy/proxies.ts
@@ -15,6 +15,7 @@ import {
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 { IAssetProxyContract } from '../../src/generated_contract_wrappers/i_asset_proxy';
import { artifacts } from '../../src/utils/artifacts';
import { expectRevertReasonOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup';
@@ -27,6 +28,11 @@ import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+const assetProxyInterface = new IAssetProxyContract(
+ artifacts.IAssetProxy.compilerOutput.abi,
+ constants.NULL_ADDRESS,
+ provider,
+);
// tslint:disable:no-unnecessary-type-assertion
describe('Asset Transfer Proxies', () => {
@@ -105,14 +111,18 @@ describe('Asset Transfer Proxies', () => {
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Proxy.transferFrom.sendTransactionAsync(
- encodedAssetData,
- makerAddress,
- takerAddress,
- amount,
- { from: exchangeAddress },
- ),
+ await web3Wrapper.sendTransactionAsync({
+ to: erc20Proxy.address,
+ data,
+ from: exchangeAddress,
+ }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
@@ -131,14 +141,18 @@ describe('Asset Transfer Proxies', () => {
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Proxy.transferFrom.sendTransactionAsync(
- encodedAssetData,
- makerAddress,
- takerAddress,
- amount,
- { from: exchangeAddress },
- ),
+ await web3Wrapper.sendTransactionAsync({
+ to: erc20Proxy.address,
+ data,
+ from: exchangeAddress,
+ }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
@@ -156,7 +170,13 @@ describe('Asset Transfer Proxies', () => {
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);
+ const amount = new BigNumber(10);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
await web3Wrapper.awaitTransactionSuccessAsync(
await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
from: makerAddress,
@@ -165,13 +185,11 @@ describe('Asset Transfer Proxies', () => {
);
// Perform a transfer; expect this to fail.
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- erc20Proxy.transferFrom.sendTransactionAsync(
- encodedAssetData,
- makerAddress,
- takerAddress,
- transferAmount,
- { from: exchangeAddress },
- ),
+ web3Wrapper.sendTransactionAsync({
+ to: erc20Proxy.address,
+ data,
+ from: exchangeAddress,
+ }),
RevertReason.TransferFailed,
);
});
@@ -179,11 +197,18 @@ describe('Asset Transfer Proxies', () => {
it('should throw if requesting address is not authorized', async () => {
// Construct ERC20 asset data
const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
-
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- erc20Proxy.transferFrom.sendTransactionAsync(encodedAssetData, makerAddress, takerAddress, amount, {
+ web3Wrapper.sendTransactionAsync({
+ to: erc20Proxy.address,
+ data,
from: notAuthorized,
}),
RevertReason.SenderNotAuthorized,
@@ -208,14 +233,18 @@ describe('Asset Transfer Proxies', () => {
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(1);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Proxy.transferFrom.sendTransactionAsync(
- encodedAssetData,
- makerAddress,
- takerAddress,
- amount,
- { from: exchangeAddress },
- ),
+ await web3Wrapper.sendTransactionAsync({
+ to: erc721Proxy.address,
+ data,
+ from: exchangeAddress,
+ }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
@@ -231,17 +260,21 @@ describe('Asset Transfer Proxies', () => {
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(
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
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);
+ const tx = await logDecoder.getTxWithDecodedLogsAsync(
+ await web3Wrapper.sendTransactionAsync({
+ to: erc721Proxy.address,
+ data,
+ from: exchangeAddress,
+ gas: constants.TRANSFER_FROM_GAS,
+ }),
+ );
// Verify that no log was emitted by erc721 receiver
expect(tx.logs.length).to.be.equal(1);
const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs<TokenReceivedContractEventArgs>;
@@ -266,17 +299,21 @@ describe('Asset Transfer Proxies', () => {
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(
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
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);
+ const tx = await logDecoder.getTxWithDecodedLogsAsync(
+ await web3Wrapper.sendTransactionAsync({
+ to: erc721Proxy.address,
+ data,
+ from: exchangeAddress,
+ gas: constants.TRANSFER_FROM_GAS,
+ }),
+ );
// Validate log emitted by erc721 receiver
expect(tx.logs.length).to.be.equal(1);
const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs<TokenReceivedContractEventArgs>;
@@ -301,14 +338,19 @@ describe('Asset Transfer Proxies', () => {
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(1);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ erc20Proxy.address, // the ERC20 proxy does not have an ERC721 receiver
+ amount,
+ );
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- erc721Proxy.transferFrom.sendTransactionAsync(
- encodedAssetData,
- makerAddress,
- erc20Proxy.address, // the ERC20 proxy does not have an ERC721 receiver
- amount,
- { from: exchangeAddress },
- ),
+ web3Wrapper.sendTransactionAsync({
+ to: erc721Proxy.address,
+ data,
+ from: exchangeAddress,
+ gas: constants.TRANSFER_FROM_GAS,
+ }),
RevertReason.TransferFailed,
);
});
@@ -321,14 +363,18 @@ describe('Asset Transfer Proxies', () => {
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(0);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- erc721Proxy.transferFrom.sendTransactionAsync(
- encodedAssetData,
- makerAddress,
- takerAddress,
- amount,
- { from: exchangeAddress },
- ),
+ web3Wrapper.sendTransactionAsync({
+ to: erc721Proxy.address,
+ data,
+ from: exchangeAddress,
+ }),
RevertReason.InvalidAmount,
);
});
@@ -341,14 +387,18 @@ describe('Asset Transfer Proxies', () => {
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(500);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- erc721Proxy.transferFrom.sendTransactionAsync(
- encodedAssetData,
- makerAddress,
- takerAddress,
- amount,
- { from: exchangeAddress },
- ),
+ web3Wrapper.sendTransactionAsync({
+ to: erc721Proxy.address,
+ data,
+ from: exchangeAddress,
+ }),
RevertReason.InvalidAmount,
);
});
@@ -358,15 +408,23 @@ describe('Asset Transfer Proxies', () => {
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Remove transfer approval for makerAddress.
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, false, {
+ await erc721Token.approve.sendTransactionAsync(constants.NULL_ADDRESS, erc721MakerTokenId, {
from: makerAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Perform a transfer; expect this to fail.
const amount = new BigNumber(1);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- erc20Proxy.transferFrom.sendTransactionAsync(encodedAssetData, makerAddress, takerAddress, amount, {
+ web3Wrapper.sendTransactionAsync({
+ to: erc721Proxy.address,
+ data,
from: exchangeAddress,
}),
RevertReason.TransferFailed,
@@ -378,14 +436,18 @@ describe('Asset Transfer Proxies', () => {
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(1);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ encodedAssetData,
+ makerAddress,
+ takerAddress,
+ amount,
+ );
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- erc721Proxy.transferFrom.sendTransactionAsync(
- encodedAssetData,
- makerAddress,
- takerAddress,
- amount,
- { from: notAuthorized },
- ),
+ web3Wrapper.sendTransactionAsync({
+ to: erc721Proxy.address,
+ data,
+ from: notAuthorized,
+ }),
RevertReason.SenderNotAuthorized,
);
});
diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts
index 0c7381aac..682de01c2 100644
--- a/packages/contracts/test/exchange/core.ts
+++ b/packages/contracts/test/exchange/core.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
-import { AssetProxyId, RevertReason, SignedOrder } from '@0xproject/types';
+import { RevertReason, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -90,8 +90,8 @@ describe('Exchange core', () => {
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC721, erc721Proxy.address, owner);
+ await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
+ await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
diff --git a/packages/contracts/test/exchange/dispatcher.ts b/packages/contracts/test/exchange/dispatcher.ts
index e35cca845..8c1052922 100644
--- a/packages/contracts/test/exchange/dispatcher.ts
+++ b/packages/contracts/test/exchange/dispatcher.ts
@@ -3,24 +3,29 @@ import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId, RevertReason } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
+import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy';
-import { TestAssetProxyDispatcherContract } from '../../src/generated_contract_wrappers/test_asset_proxy_dispatcher';
+import {
+ AssetProxyRegisteredContractEventArgs,
+ TestAssetProxyDispatcherContract,
+} from '../../src/generated_contract_wrappers/test_asset_proxy_dispatcher';
import { artifacts } from '../../src/utils/artifacts';
import { expectRevertReasonOrAlwaysFailingTransactionAsync } 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 { 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('AssetProxyDispatcher', () => {
let owner: string;
let notOwner: string;
@@ -82,14 +87,8 @@ describe('AssetProxyDispatcher', () => {
});
describe('registerAssetProxy', () => {
it('should record proxy upon registration', async () => {
- const prevProxyAddress = constants.NULL_ADDRESS;
await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- prevProxyAddress,
- { from: owner },
- ),
+ await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
@@ -98,46 +97,30 @@ describe('AssetProxyDispatcher', () => {
it('should be able to record multiple proxies', async () => {
// Record first proxy
- const prevERC20ProxyAddress = constants.NULL_ADDRESS;
await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- prevERC20ProxyAddress,
- { from: owner },
- ),
+ await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
let proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
expect(proxyAddress).to.be.equal(erc20Proxy.address);
// Record another proxy
- const prevERC721ProxyAddress = constants.NULL_ADDRESS;
await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC721,
- erc721Proxy.address,
- prevERC721ProxyAddress,
- { from: owner },
- ),
+ await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc721Proxy.address, {
+ from: owner,
+ }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC721);
expect(proxyAddress).to.be.equal(erc721Proxy.address);
});
- it('should replace proxy address upon re-registration', async () => {
+ it('should throw if a proxy with the same id is already registered', async () => {
// Initial registration
- const prevProxyAddress = constants.NULL_ADDRESS;
await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- prevProxyAddress,
- { from: owner },
- ),
+ await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
- let proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
+ const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
expect(proxyAddress).to.be.equal(erc20Proxy.address);
// Deploy a new version of the ERC20 Transfer Proxy contract
const newErc20TransferProxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
@@ -146,114 +129,37 @@ describe('AssetProxyDispatcher', () => {
txDefaults,
);
// Register new ERC20 Transfer Proxy contract
- const newAddress = newErc20TransferProxy.address;
- const currentAddress = erc20Proxy.address;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- newAddress,
- currentAddress,
- { from: owner },
- ),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- // Verify new asset proxy has replaced initial version
- proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
- expect(proxyAddress).to.be.equal(newAddress);
- });
-
- it('should throw if registering with incorrect "currentAssetProxyAddress" field', async () => {
- // Initial registration
- const prevProxyAddress = constants.NULL_ADDRESS;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- prevProxyAddress,
- { from: owner },
- ),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
- expect(proxyAddress).to.be.equal(erc20Proxy.address);
- // The following transaction will throw because the currentAddress is no longer constants.NULL_ADDRESS
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- constants.NULL_ADDRESS,
- { from: owner },
- ),
- RevertReason.AssetProxyMismatch,
+ assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(newErc20TransferProxy.address, {
+ from: owner,
+ }),
+ RevertReason.AssetProxyAlreadyExists,
);
});
- it('should be able to reset proxy address to NULL', async () => {
- // Initial registration
- const prevProxyAddress = constants.NULL_ADDRESS;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- prevProxyAddress,
- { from: owner },
- ),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
- expect(proxyAddress).to.be.equal(erc20Proxy.address);
- // The following transaction will reset the proxy address
- const newProxyAddress = constants.NULL_ADDRESS;
- await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- newProxyAddress,
- erc20Proxy.address,
- { from: owner },
- ),
- constants.AWAIT_TRANSACTION_MINED_MS,
- );
- const finalProxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
- expect(finalProxyAddress).to.be.equal(newProxyAddress);
- });
-
it('should throw if requesting address is not owner', async () => {
- const prevProxyAddress = constants.NULL_ADDRESS;
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- prevProxyAddress,
- { from: notOwner },
- ),
+ assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: notOwner }),
RevertReason.OnlyContractOwner,
);
});
- it('should throw if attempting to register a proxy to the incorrect id', async () => {
- const prevProxyAddress = constants.NULL_ADDRESS;
- return expectRevertReasonOrAlwaysFailingTransactionAsync(
- assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC721,
- erc20Proxy.address,
- prevProxyAddress,
- { from: owner },
- ),
- RevertReason.AssetProxyIdMismatch,
+ it('should log an event with correct arguments when an asset proxy is registered', async () => {
+ const logDecoder = new LogDecoder(web3Wrapper, assetProxyDispatcher.address);
+ const txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
+ await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
);
+ const logs = txReceipt.logs;
+ const log = logs[0] as LogWithDecodedArgs<AssetProxyRegisteredContractEventArgs>;
+ expect(log.args.id).to.equal(AssetProxyId.ERC20);
+ expect(log.args.assetProxy).to.equal(erc20Proxy.address);
});
});
describe('getAssetProxy', () => {
it('should return correct address of registered proxy', async () => {
- const prevProxyAddress = constants.NULL_ADDRESS;
await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- prevProxyAddress,
- { from: owner },
- ),
+ await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
@@ -269,14 +175,8 @@ describe('AssetProxyDispatcher', () => {
describe('dispatchTransferFrom', () => {
it('should dispatch transfer to registered proxy', async () => {
// Register ERC20 proxy
- const prevProxyAddress = constants.NULL_ADDRESS;
await web3Wrapper.awaitTransactionSuccessAsync(
- await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
- AssetProxyId.ERC20,
- erc20Proxy.address,
- prevProxyAddress,
- { from: owner },
- ),
+ await assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Construct metadata for ERC20 proxy
@@ -323,3 +223,4 @@ describe('AssetProxyDispatcher', () => {
});
});
});
+// tslint:enable:no-unnecessary-type-assertion
diff --git a/packages/contracts/test/exchange/match_orders.ts b/packages/contracts/test/exchange/match_orders.ts
index e23ab9851..3ebe7e690 100644
--- a/packages/contracts/test/exchange/match_orders.ts
+++ b/packages/contracts/test/exchange/match_orders.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
-import { AssetProxyId, RevertReason } from '@0xproject/types';
+import { RevertReason } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -103,8 +103,8 @@ describe('matchOrders', () => {
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC721, erc721Proxy.address, owner);
+ await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
+ await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
// Authorize ERC20 and ERC721 trades by exchange
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
@@ -651,13 +651,7 @@ describe('matchOrders', () => {
});
// Match orders
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- matchOrderTester.matchOrdersAndVerifyBalancesAsync(
- signedOrderLeft,
- signedOrderRight,
- takerAddress,
- erc20BalancesByOwner,
- erc721TokenIdsByOwner,
- ),
+ exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress),
RevertReason.NegativeSpreadRequired,
);
});
@@ -680,13 +674,7 @@ describe('matchOrders', () => {
});
// Match orders
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- matchOrderTester.matchOrdersAndVerifyBalancesAsync(
- signedOrderLeft,
- signedOrderRight,
- takerAddress,
- erc20BalancesByOwner,
- erc721TokenIdsByOwner,
- ),
+ exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress),
// We are assuming assetData fields of the right order are the
// reverse of the left order, rather than checking equality. This
// saves a bunch of gas, but as a result if the assetData fields are
@@ -715,13 +703,7 @@ describe('matchOrders', () => {
});
// Match orders
return expectRevertReasonOrAlwaysFailingTransactionAsync(
- matchOrderTester.matchOrdersAndVerifyBalancesAsync(
- signedOrderLeft,
- signedOrderRight,
- takerAddress,
- erc20BalancesByOwner,
- erc721TokenIdsByOwner,
- ),
+ exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress),
RevertReason.InvalidOrderSignature,
);
});
diff --git a/packages/contracts/test/exchange/transactions.ts b/packages/contracts/test/exchange/transactions.ts
index c4de58bb9..23441e7f8 100644
--- a/packages/contracts/test/exchange/transactions.ts
+++ b/packages/contracts/test/exchange/transactions.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
-import { AssetProxyId, OrderWithoutExchangeAddress, RevertReason, SignedOrder } from '@0xproject/types';
+import { OrderWithoutExchangeAddress, RevertReason, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
@@ -91,7 +91,7 @@ describe('Exchange transactions', () => {
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner);
+ await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner }),
diff --git a/packages/contracts/test/exchange/wrapper.ts b/packages/contracts/test/exchange/wrapper.ts
index 1af8bde9d..6abb660a8 100644
--- a/packages/contracts/test/exchange/wrapper.ts
+++ b/packages/contracts/test/exchange/wrapper.ts
@@ -1,6 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils';
-import { AssetProxyId, RevertReason, SignedOrder } from '@0xproject/types';
+import { RevertReason, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai';
@@ -87,8 +87,8 @@ describe('Exchange wrappers', () => {
assetProxyUtils.encodeERC20AssetData(zrxToken.address),
);
exchangeWrapper = new ExchangeWrapper(exchange, provider);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC20, erc20Proxy.address, owner);
- await exchangeWrapper.registerAssetProxyAsync(AssetProxyId.ERC721, erc721Proxy.address, owner);
+ await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner);
+ await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, {
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 4b70c36f9..4ad10fdee 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -187,8 +187,7 @@ export enum RevertReason {
InvalidTxHash = 'INVALID_TX_HASH',
InvalidTxSignature = 'INVALID_TX_SIGNATURE',
FailedExecution = 'FAILED_EXECUTION',
- AssetProxyMismatch = 'ASSET_PROXY_MISMATCH',
- AssetProxyIdMismatch = 'ASSET_PROXY_ID_MISMATCH',
+ AssetProxyAlreadyExists = 'ASSET_PROXY_ALREADY_EXISTS',
LengthGreaterThan0Required = 'LENGTH_GREATER_THAN_0_REQUIRED',
LengthGreaterThan131Required = 'LENGTH_GREATER_THAN_131_REQUIRED',
Length0Required = 'LENGTH_0_REQUIRED',
diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx
index 23387a95a..c7ccfdf1f 100644
--- a/packages/website/ts/index.tsx
+++ b/packages/website/ts/index.tsx
@@ -97,7 +97,6 @@ render(
<Route path={WebsitePaths.FAQ} component={FAQ as any} />
<Route path={WebsitePaths.About} component={About as any} />
<Route path={WebsitePaths.Wiki} component={Wiki as any} />
- <Route path={`${WebsitePaths.Docs}`} component={LazyZeroExJSDocumentation} />
<Route path={`${WebsitePaths.ZeroExJs}/:version?`} component={LazyZeroExJSDocumentation} />
<Route path={`${WebsitePaths.Connect}/:version?`} component={LazyConnectDocumentation} />
<Route
@@ -144,6 +143,7 @@ render(
component={LazySolCompilerDocumentation}
/>
+ <Route path={`${WebsitePaths.Docs}`} component={LazyZeroExJSDocumentation} />
<Route component={NotFound as any} />
</Switch>
</div>
diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts
index 2f89f8ccb..e8a486c35 100644
--- a/packages/website/ts/utils/configs.ts
+++ b/packages/website/ts/utils/configs.ts
@@ -11,7 +11,7 @@ const INFURA_API_KEY = 'T5WSC8cautR4KXyYgsRs';
export const configs = {
AMOUNT_DISPLAY_PRECSION: 5,
BACKEND_BASE_PROD_URL: 'https://website-api.0xproject.com',
- BACKEND_BASE_STAGING_URL: 'http://ec2-52-91-181-85.compute-1.amazonaws.com',
+ BACKEND_BASE_STAGING_URL: 'https://staging-website-api.0xproject.com',
BASE_URL,
BITLY_ACCESS_TOKEN: 'ffc4c1a31e5143848fb7c523b39f91b9b213d208',
DEFAULT_DERIVATION_PATH: `44'/60'/0'`,