Merge branch 'development' into feature/contracts/coordinator-tx-eip712-mixed-domains
This commit is contained in:
		@@ -9,6 +9,10 @@
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Do not reexport external dependencies",
 | 
			
		||||
                "pr": 1682
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add ERC1155Proxy",
 | 
			
		||||
                "pr": 1661
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "contracts": [
 | 
			
		||||
        "src/ERC1155Proxy.sol",
 | 
			
		||||
        "src/ERC20Proxy.sol",
 | 
			
		||||
        "src/ERC721Proxy.sol",
 | 
			
		||||
        "src/MixinAuthorizable.sol",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										267
									
								
								contracts/asset-proxy/contracts/src/ERC1155Proxy.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								contracts/asset-proxy/contracts/src/ERC1155Proxy.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,267 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  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 "./MixinAuthorizable.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract ERC1155Proxy is
 | 
			
		||||
    MixinAuthorizable
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    // Id of this proxy.
 | 
			
		||||
    bytes4 constant internal PROXY_ID = bytes4(keccak256("ERC1155Token(address,uint256[],uint256[],bytes)"));
 | 
			
		||||
 | 
			
		||||
    function () 
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        // Input calldata to this function is encoded as follows:
 | 
			
		||||
        //                      -- TABLE #1 --
 | 
			
		||||
        // | 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         | (see below) | assetData Contents              |
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        // Asset data is encoded as follows:
 | 
			
		||||
        //                      -- TABLE #2 --
 | 
			
		||||
        // | Area     | Offset      | Length  | Contents                            |
 | 
			
		||||
        // |----------|-------------|---------|-------------------------------------|
 | 
			
		||||
        // | Header   | 0           | 4       | assetProxyId                        |
 | 
			
		||||
        // | Params   |             | 4 * 32  | function parameters:                |
 | 
			
		||||
        // |          | 4           |         |   1. address of ERC1155 contract    |
 | 
			
		||||
        // |          | 36          |         |   2. offset to ids (*)              |
 | 
			
		||||
        // |          | 68          |         |   3. offset to values (*)           |
 | 
			
		||||
        // |          | 100         |         |   4. offset to data (*)             |
 | 
			
		||||
        // | Data     |             |         | ids:                                |
 | 
			
		||||
        // |          | 132         | 32      |   1. ids Length                     |
 | 
			
		||||
        // |          | 164         | a       |   2. ids Contents                   | 
 | 
			
		||||
        // |          |             |         | values:                             |
 | 
			
		||||
        // |          | 164 + a     | 32      |   1. values Length                  |
 | 
			
		||||
        // |          | 196 + a     | b       |   2. values Contents                |
 | 
			
		||||
        // |          |             |         | data                                |
 | 
			
		||||
        // |          | 196 + a + b | 32      |   1. data Length                    |
 | 
			
		||||
        // |          | 228 + a + b | c       |   2. data Contents                  |
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        // Calldata for target ERC155 asset is encoded for safeBatchTransferFrom:
 | 
			
		||||
        //                      -- TABLE #3 --
 | 
			
		||||
        // | Area     | Offset (**) | Length  | Contents                            |
 | 
			
		||||
        // |----------|-------------|---------|-------------------------------------|
 | 
			
		||||
        // | Header   | 0           | 4       | safeBatchTransferFrom selector      |
 | 
			
		||||
        // | Params   |             | 5 * 32  | function parameters:                |
 | 
			
		||||
        // |          | 4           |         |   1. from address                   |
 | 
			
		||||
        // |          | 36          |         |   2. to address                     |
 | 
			
		||||
        // |          | 68          |         |   3. offset to ids (*)              |
 | 
			
		||||
        // |          | 100         |         |   4. offset to values (*)           |
 | 
			
		||||
        // |          | 132         |         |   5. offset to data (*)             |
 | 
			
		||||
        // | Data     |             |         | ids:                                |
 | 
			
		||||
        // |          | 164         | 32      |   1. ids Length                     |
 | 
			
		||||
        // |          | 196         | a       |   2. ids Contents                   | 
 | 
			
		||||
        // |          |             |         | values:                             |
 | 
			
		||||
        // |          | 196 + a     | 32      |   1. values Length                  |
 | 
			
		||||
        // |          | 228 + a     | b       |   2. values Contents                |
 | 
			
		||||
        // |          |             |         | data                                |
 | 
			
		||||
        // |          | 228 + a + b | 32      |   1. data Length                    |
 | 
			
		||||
        // |          | 260 + a + b | c       |   2. data Contents                  |
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        // (*): offset is computed from start of function parameters, so offset
 | 
			
		||||
        //      by an additional 4 bytes in the calldata.
 | 
			
		||||
        // 
 | 
			
		||||
        // (**): the `Offset` column is computed assuming no calldata compression;
 | 
			
		||||
        //       offsets in the Data Area are dynamic and should be evaluated in
 | 
			
		||||
        //       real-time.
 | 
			
		||||
        //
 | 
			
		||||
        // WARNING: The ABIv2 specification allows additional padding between
 | 
			
		||||
        //          the Params and Data section. This will result in a larger
 | 
			
		||||
        //          offset to assetData.
 | 
			
		||||
        //
 | 
			
		||||
        // Note: Table #1 and Table #2 exists in Calldata. We construct Table #3 in memory. 
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        assembly {
 | 
			
		||||
            // 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
 | 
			
		||||
                mstore(0, caller)
 | 
			
		||||
                mstore(32, authorized_slot)
 | 
			
		||||
 | 
			
		||||
                 // Revert if authorized[msg.sender] == false
 | 
			
		||||
                if iszero(sload(keccak256(0, 64))) {
 | 
			
		||||
                    // Revert with `Error("SENDER_NOT_AUTHORIZED")`
 | 
			
		||||
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                    mstore(64, 0x0000001553454e4445525f4e4f545f415554484f52495a454400000000000000)
 | 
			
		||||
                    mstore(96, 0)
 | 
			
		||||
                    revert(0, 100)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Construct Table #3 in memory, starting at memory offset 0.
 | 
			
		||||
                // The algorithm below maps asset data from Table #1 and Table #2 to Table #3, while
 | 
			
		||||
                // scaling the `values` (Table #2) by `amount` (Table #1). Once Table #3 has
 | 
			
		||||
                // been constructed in memory, the destination erc1155 contract is called using this 
 | 
			
		||||
                // as its calldata. This process is divided into four steps, below.
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 1/4 //////////
 | 
			
		||||
                // Map relevant fields from assetData (Table #2) into memory (Table #3)
 | 
			
		||||
                // The Contents column of Table #2 is the same as Table #3,
 | 
			
		||||
                // beginning from parameter 3 - `offset to ids (*)`
 | 
			
		||||
                // The offsets in these rows are offset by 32 bytes in Table #3.
 | 
			
		||||
                // Strategy:
 | 
			
		||||
                // 1. Copy the assetData into memory at offset 32
 | 
			
		||||
                // 2. Increment by 32 the offsets to `ids`, `values`, and `data`
 | 
			
		||||
 | 
			
		||||
                // Load offset to `assetData`
 | 
			
		||||
                let assetDataOffset := calldataload(4)
 | 
			
		||||
 | 
			
		||||
                // Load length in bytes of `assetData`, computed by:
 | 
			
		||||
                // 4 (function selector)
 | 
			
		||||
                // + assetDataOffset
 | 
			
		||||
                let assetDataLength := calldataload(add(4, assetDataOffset))
 | 
			
		||||
 | 
			
		||||
                // This corresponds to the beginning of the Data Area for Table #3.
 | 
			
		||||
                // Computed by:
 | 
			
		||||
                // 4 (function selector)
 | 
			
		||||
                // + assetDataOffset
 | 
			
		||||
                // + 32 (length of assetData)
 | 
			
		||||
                calldatacopy(
 | 
			
		||||
                    32,                         // aligned such that "offset to ids" is at the correct location for Table #3
 | 
			
		||||
                    add(36, assetDataOffset),   // beginning of asset data contents
 | 
			
		||||
                    assetDataLength             // length of asset data
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // Increment by 32 the offsets to `ids`, `values`, and `data`
 | 
			
		||||
                mstore(68, add(mload(68), 32))
 | 
			
		||||
                mstore(100, add(mload(100), 32))
 | 
			
		||||
                mstore(132, add(mload(132), 32))
 | 
			
		||||
 | 
			
		||||
                // Record the address of the destination erc1155 asset for later.
 | 
			
		||||
                let assetAddress := and(
 | 
			
		||||
                    mload(36),
 | 
			
		||||
                    0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 2/4 //////////
 | 
			
		||||
                let amount := calldataload(100)
 | 
			
		||||
                let valuesOffset := add(mload(100), 4) // add 4 for calldata offset
 | 
			
		||||
                let valuesLengthInBytes := mul(
 | 
			
		||||
                    mload(valuesOffset),
 | 
			
		||||
                    32
 | 
			
		||||
                )
 | 
			
		||||
                let valuesBegin := add(valuesOffset, 32)
 | 
			
		||||
                let valuesEnd := add(valuesBegin, valuesLengthInBytes)
 | 
			
		||||
                for { let tokenValueOffset := valuesBegin }
 | 
			
		||||
                    lt(tokenValueOffset, valuesEnd)
 | 
			
		||||
                    { tokenValueOffset := add(tokenValueOffset, 32) }
 | 
			
		||||
                {
 | 
			
		||||
                    // Load token value and generate scaled value
 | 
			
		||||
                    let tokenValue := mload(tokenValueOffset)
 | 
			
		||||
                    let scaledTokenValue := mul(tokenValue, amount)
 | 
			
		||||
 | 
			
		||||
                    // Revert if `amount` != 0 and multiplication resulted in an overflow
 | 
			
		||||
                    if iszero(or(
 | 
			
		||||
                        iszero(amount),
 | 
			
		||||
                        eq(div(scaledTokenValue, amount), tokenValue)
 | 
			
		||||
                    )) {
 | 
			
		||||
                        // Revert with `Error("UINT256_OVERFLOW")`
 | 
			
		||||
                        mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                        mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
                        mstore(64, 0x0000001055494e543235365f4f564552464c4f57000000000000000000000000)
 | 
			
		||||
                        mstore(96, 0)
 | 
			
		||||
                        revert(0, 100)
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // There was no overflow, update `tokenValue` with its scaled counterpart
 | 
			
		||||
                    mstore(tokenValueOffset, scaledTokenValue)
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 3/4 //////////
 | 
			
		||||
                // Store the safeBatchTransferFrom function selector,
 | 
			
		||||
                // and copy `from`/`to` fields from Table #1 to Table #3.
 | 
			
		||||
 | 
			
		||||
                // The function selector is computed using:
 | 
			
		||||
                // bytes4(keccak256("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)"))
 | 
			
		||||
                mstore(0, 0x2eb2c2d600000000000000000000000000000000000000000000000000000000)
 | 
			
		||||
 | 
			
		||||
                // Copy `from` and `to` fields from Table #1 to Table #3
 | 
			
		||||
                calldatacopy(
 | 
			
		||||
                    4,          // aligned such that `from` and `to` are at the correct location for Table #3
 | 
			
		||||
                    36,         // beginning of `from` field from Table #1
 | 
			
		||||
                    64          // 32 bytes for `from` + 32 bytes for `to` field
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                ////////// STEP 4/4 //////////
 | 
			
		||||
                // Call into the destination erc1155 contract using as calldata Table #3 (constructed in-memory above)
 | 
			
		||||
                let success := call(
 | 
			
		||||
                    gas,                                    // forward all gas
 | 
			
		||||
                    assetAddress,                           // call address of erc1155 asset
 | 
			
		||||
                    0,                                      // don't send any ETH
 | 
			
		||||
                    0,                                      // pointer to start of input
 | 
			
		||||
                    add(assetDataLength, 32),               // length of input (Table #3) is 32 bytes longer than `assetData` (Table #2)
 | 
			
		||||
                    0,                                      // write output over memory that won't be reused
 | 
			
		||||
                    0                                       // don't copy output to memory
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
                // Revert with reason given by AssetProxy if `transferFrom` call failed
 | 
			
		||||
                if iszero(success) {
 | 
			
		||||
                    returndatacopy(
 | 
			
		||||
                        0,                // copy to memory at 0
 | 
			
		||||
                        0,                // copy from return data at 0
 | 
			
		||||
                        returndatasize()  // copy all return data
 | 
			
		||||
                    )
 | 
			
		||||
                    revert(0, returndatasize())
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // Return if call was successful
 | 
			
		||||
                return(0, 0)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Revert if undefined function is called
 | 
			
		||||
            revert(0, 0)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Gets the proxy id associated with the proxy address.
 | 
			
		||||
    /// @return Proxy id.
 | 
			
		||||
    function getProxyId()
 | 
			
		||||
        external
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes4)
 | 
			
		||||
    {
 | 
			
		||||
        return PROXY_ID;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -33,7 +33,7 @@
 | 
			
		||||
        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "abis": "./generated-artifacts/@(ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|MixinAuthorizable|MultiAssetProxy).json",
 | 
			
		||||
        "abis": "./generated-artifacts/@(ERC1155Proxy|ERC20Proxy|ERC721Proxy|IAssetData|IAssetProxy|IAuthorizable|MixinAuthorizable|MultiAssetProxy).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
@@ -70,6 +70,7 @@
 | 
			
		||||
        "@0x/base-contract": "^5.0.2",
 | 
			
		||||
        "@0x/contracts-erc20": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-erc721": "^1.0.9",
 | 
			
		||||
        "@0x/contracts-erc1155": "^1.0.0",
 | 
			
		||||
        "@0x/contracts-utils": "2.0.1",
 | 
			
		||||
        "@0x/order-utils": "^7.0.2",
 | 
			
		||||
        "@0x/types": "^2.1.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
 | 
			
		||||
import * as ERC20Proxy from '../generated-artifacts/ERC20Proxy.json';
 | 
			
		||||
import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
 | 
			
		||||
import * as IAssetData from '../generated-artifacts/IAssetData.json';
 | 
			
		||||
@@ -15,6 +16,7 @@ import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    ERC20Proxy: ERC20Proxy as ContractArtifact,
 | 
			
		||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
			
		||||
    ERC1155Proxy: ERC1155Proxy as ContractArtifact,
 | 
			
		||||
    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
			
		||||
    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
			
		||||
    IAssetData: IAssetData as ContractArtifact,
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../generated-wrappers/erc1155_proxy';
 | 
			
		||||
export * from '../generated-wrappers/erc20_proxy';
 | 
			
		||||
export * from '../generated-wrappers/erc721_proxy';
 | 
			
		||||
export * from '../generated-wrappers/i_asset_data';
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										790
									
								
								contracts/asset-proxy/test/erc1155_proxy.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										790
									
								
								contracts/asset-proxy/test/erc1155_proxy.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,790 @@
 | 
			
		||||
import {
 | 
			
		||||
    artifacts as erc1155Artifacts,
 | 
			
		||||
    DummyERC1155ReceiverBatchTokenReceivedEventArgs,
 | 
			
		||||
    DummyERC1155ReceiverContract,
 | 
			
		||||
    ERC1155MintableContract,
 | 
			
		||||
    Erc1155Wrapper,
 | 
			
		||||
} from '@0x/contracts-erc1155';
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
    expectTransactionFailedAsync,
 | 
			
		||||
    expectTransactionFailedWithoutReasonAsync,
 | 
			
		||||
    provider,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { RevertReason } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { ERC1155ProxyWrapper, ERC721ProxyContract } from '../src';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
// tslint:disable:no-unnecessary-type-assertion
 | 
			
		||||
describe('ERC1155Proxy', () => {
 | 
			
		||||
    // constant values used in transfer tests
 | 
			
		||||
    const nftOwnerBalance = new BigNumber(1);
 | 
			
		||||
    const nftNotOwnerBalance = new BigNumber(0);
 | 
			
		||||
    const spenderInitialFungibleBalance = constants.INITIAL_ERC1155_FUNGIBLE_BALANCE;
 | 
			
		||||
    const receiverInitialFungibleBalance = constants.INITIAL_ERC1155_FUNGIBLE_BALANCE;
 | 
			
		||||
    const receiverContractInitialFungibleBalance = new BigNumber(0);
 | 
			
		||||
    const fungibleValueToTransferSmall = spenderInitialFungibleBalance.div(100);
 | 
			
		||||
    const fungibleValueToTransferLarge = spenderInitialFungibleBalance.div(4);
 | 
			
		||||
    const valueMultiplierSmall = new BigNumber(2);
 | 
			
		||||
    const valueMultiplierNft = new BigNumber(1);
 | 
			
		||||
    const nonFungibleValueToTransfer = nftOwnerBalance;
 | 
			
		||||
    const receiverCallbackData = '0x01020304';
 | 
			
		||||
    // addresses
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let notAuthorized: string;
 | 
			
		||||
    let authorized: string;
 | 
			
		||||
    let spender: string;
 | 
			
		||||
    let receiver: string;
 | 
			
		||||
    let receiverContract: string;
 | 
			
		||||
    // contracts & wrappers
 | 
			
		||||
    let erc1155Proxy: ERC721ProxyContract;
 | 
			
		||||
    let erc1155Receiver: DummyERC1155ReceiverContract;
 | 
			
		||||
    let erc1155ProxyWrapper: ERC1155ProxyWrapper;
 | 
			
		||||
    let erc1155Contract: ERC1155MintableContract;
 | 
			
		||||
    let erc1155Wrapper: Erc1155Wrapper;
 | 
			
		||||
    // tokens
 | 
			
		||||
    let fungibleTokens: BigNumber[];
 | 
			
		||||
    let nonFungibleTokensOwnedBySpender: BigNumber[];
 | 
			
		||||
    // tests
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        /// deploy & configure ERC1155Proxy
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        const usedAddresses = ([owner, notAuthorized, authorized, spender, receiver] = _.slice(accounts, 0, 5));
 | 
			
		||||
        erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner);
 | 
			
		||||
        erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync();
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(erc1155Proxy.address, {
 | 
			
		||||
                from: owner,
 | 
			
		||||
            }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
        // deploy & configure ERC1155 tokens and receiver
 | 
			
		||||
        [erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyContractsAsync();
 | 
			
		||||
        erc1155Contract = erc1155Wrapper.getContract();
 | 
			
		||||
        erc1155Receiver = await DummyERC1155ReceiverContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            erc1155Artifacts.DummyERC1155Receiver,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        receiverContract = erc1155Receiver.address;
 | 
			
		||||
        await erc1155ProxyWrapper.setBalancesAndAllowancesAsync();
 | 
			
		||||
        fungibleTokens = erc1155ProxyWrapper.getFungibleTokenIds();
 | 
			
		||||
        const nonFungibleTokens = erc1155ProxyWrapper.getNonFungibleTokenIds();
 | 
			
		||||
        const tokenBalances = await erc1155ProxyWrapper.getBalancesAsync();
 | 
			
		||||
        nonFungibleTokensOwnedBySpender = [];
 | 
			
		||||
        _.each(nonFungibleTokens, (nonFungibleToken: BigNumber) => {
 | 
			
		||||
            const nonFungibleTokenAsString = nonFungibleToken.toString();
 | 
			
		||||
            const nonFungibleTokenHeldBySpender =
 | 
			
		||||
                tokenBalances.nonFungible[spender][erc1155Contract.address][nonFungibleTokenAsString][0];
 | 
			
		||||
            nonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    describe('general', () => {
 | 
			
		||||
        it('should revert if undefined function is called', async () => {
 | 
			
		||||
            const undefinedSelector = '0x01020304';
 | 
			
		||||
            await expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
                web3Wrapper.sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                    to: erc1155Proxy.address,
 | 
			
		||||
                    value: constants.ZERO_AMOUNT,
 | 
			
		||||
                    data: undefinedSelector,
 | 
			
		||||
                }),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should have an id of 0x9645780d', async () => {
 | 
			
		||||
            const proxyId = await erc1155Proxy.getProxyId.callAsync();
 | 
			
		||||
            // proxy computed using -- bytes4(keccak256("erc1155Token(address,uint256[],uint256[],bytes)"));
 | 
			
		||||
            const expectedProxyId = '0x9645780d';
 | 
			
		||||
            expect(proxyId).to.equal(expectedProxyId);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('transferFrom', () => {
 | 
			
		||||
        it('should successfully transfer value for a single, fungible token', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const totalValueTransferred = valuesToTransfer[0].times(valueMultiplier);
 | 
			
		||||
            const expectedFinalBalances = [
 | 
			
		||||
                spenderInitialFungibleBalance.minus(totalValueTransferred),
 | 
			
		||||
                receiverInitialFungibleBalance.plus(totalValueTransferred),
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should successfully transfer value for the same fungible token several times', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokenToTransfer = fungibleTokens[0];
 | 
			
		||||
            const tokensToTransfer = [tokenToTransfer, tokenToTransfer, tokenToTransfer];
 | 
			
		||||
            const valuesToTransfer = [
 | 
			
		||||
                fungibleValueToTransferSmall.plus(10),
 | 
			
		||||
                fungibleValueToTransferSmall.plus(20),
 | 
			
		||||
                fungibleValueToTransferSmall.plus(30),
 | 
			
		||||
            ];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                spenderInitialFungibleBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                receiverInitialFungibleBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            let totalValueTransferred = _.reduce(valuesToTransfer, (sum: BigNumber, value: BigNumber) => {
 | 
			
		||||
                return sum.plus(value);
 | 
			
		||||
            }) as BigNumber;
 | 
			
		||||
            totalValueTransferred = totalValueTransferred.times(valueMultiplier);
 | 
			
		||||
            const expectedFinalBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                spenderInitialFungibleBalance.minus(totalValueTransferred),
 | 
			
		||||
                // receiver
 | 
			
		||||
                receiverInitialFungibleBalance.plus(totalValueTransferred),
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should successfully transfer value for several fungible tokens', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 3);
 | 
			
		||||
            const valuesToTransfer = [
 | 
			
		||||
                fungibleValueToTransferSmall.plus(10),
 | 
			
		||||
                fungibleValueToTransferSmall.plus(20),
 | 
			
		||||
                fungibleValueToTransferSmall.plus(30),
 | 
			
		||||
            ];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                spenderInitialFungibleBalance,
 | 
			
		||||
                spenderInitialFungibleBalance,
 | 
			
		||||
                spenderInitialFungibleBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                receiverInitialFungibleBalance,
 | 
			
		||||
                receiverInitialFungibleBalance,
 | 
			
		||||
                receiverInitialFungibleBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
 | 
			
		||||
                return value.times(valueMultiplier);
 | 
			
		||||
            });
 | 
			
		||||
            const expectedFinalBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                spenderInitialFungibleBalance.minus(totalValuesTransferred[0]),
 | 
			
		||||
                spenderInitialFungibleBalance.minus(totalValuesTransferred[1]),
 | 
			
		||||
                spenderInitialFungibleBalance.minus(totalValuesTransferred[2]),
 | 
			
		||||
                // receiver
 | 
			
		||||
                receiverInitialFungibleBalance.plus(totalValuesTransferred[0]),
 | 
			
		||||
                receiverInitialFungibleBalance.plus(totalValuesTransferred[1]),
 | 
			
		||||
                receiverInitialFungibleBalance.plus(totalValuesTransferred[2]),
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should successfully transfer a non-fungible token', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [nonFungibleValueToTransfer];
 | 
			
		||||
            const valueMultiplier = valueMultiplierNft;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const expectedFinalBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should successfully transfer multiple non-fungible tokens', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 3);
 | 
			
		||||
            const valuesToTransfer = [
 | 
			
		||||
                nonFungibleValueToTransfer,
 | 
			
		||||
                nonFungibleValueToTransfer,
 | 
			
		||||
                nonFungibleValueToTransfer,
 | 
			
		||||
            ];
 | 
			
		||||
            const valueMultiplier = valueMultiplierNft;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const expectedFinalBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should successfully transfer value for a combination of several fungible/non-fungible tokens', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const fungibleTokensToTransfer = fungibleTokens.slice(0, 3);
 | 
			
		||||
            const nonFungibleTokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 2);
 | 
			
		||||
            const tokensToTransfer = fungibleTokensToTransfer.concat(nonFungibleTokensToTransfer);
 | 
			
		||||
            const valuesToTransfer = [
 | 
			
		||||
                fungibleValueToTransferLarge,
 | 
			
		||||
                fungibleValueToTransferSmall,
 | 
			
		||||
                fungibleValueToTransferSmall,
 | 
			
		||||
                nonFungibleValueToTransfer,
 | 
			
		||||
                nonFungibleValueToTransfer,
 | 
			
		||||
            ];
 | 
			
		||||
            const valueMultiplier = valueMultiplierNft;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                spenderInitialFungibleBalance,
 | 
			
		||||
                spenderInitialFungibleBalance,
 | 
			
		||||
                spenderInitialFungibleBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                receiverInitialFungibleBalance,
 | 
			
		||||
                receiverInitialFungibleBalance,
 | 
			
		||||
                receiverInitialFungibleBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
 | 
			
		||||
                return value.times(valueMultiplier);
 | 
			
		||||
            });
 | 
			
		||||
            const expectedFinalBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                expectedInitialBalances[0].minus(totalValuesTransferred[0]),
 | 
			
		||||
                expectedInitialBalances[1].minus(totalValuesTransferred[1]),
 | 
			
		||||
                expectedInitialBalances[2].minus(totalValuesTransferred[2]),
 | 
			
		||||
                expectedInitialBalances[3].minus(totalValuesTransferred[3]),
 | 
			
		||||
                expectedInitialBalances[4].minus(totalValuesTransferred[4]),
 | 
			
		||||
                // receiver
 | 
			
		||||
                expectedInitialBalances[5].plus(totalValuesTransferred[0]),
 | 
			
		||||
                expectedInitialBalances[6].plus(totalValuesTransferred[1]),
 | 
			
		||||
                expectedInitialBalances[7].plus(totalValuesTransferred[2]),
 | 
			
		||||
                expectedInitialBalances[8].plus(totalValuesTransferred[3]),
 | 
			
		||||
                expectedInitialBalances[9].plus(totalValuesTransferred[4]),
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should successfully transfer value to a smart contract and trigger its callback', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiverContract];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
 | 
			
		||||
                return value.times(valueMultiplier);
 | 
			
		||||
            });
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverContractInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            const txReceipt = await erc1155ProxyWrapper.transferFromWithLogsAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiverContract,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check receiver log ignored extra asset data
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(2);
 | 
			
		||||
            const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<
 | 
			
		||||
                DummyERC1155ReceiverBatchTokenReceivedEventArgs
 | 
			
		||||
            >;
 | 
			
		||||
            expect(receiverLog.args.operator).to.be.equal(erc1155Proxy.address);
 | 
			
		||||
            expect(receiverLog.args.from).to.be.equal(spender);
 | 
			
		||||
            expect(receiverLog.args.tokenIds.length).to.be.deep.equal(1);
 | 
			
		||||
            expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokensToTransfer[0]);
 | 
			
		||||
            expect(receiverLog.args.tokenValues.length).to.be.deep.equal(1);
 | 
			
		||||
            expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(totalValuesTransferred[0]);
 | 
			
		||||
            // note - if the `extraData` is ignored then the receiver log should ignore it as well.
 | 
			
		||||
            expect(receiverLog.args.data).to.be.deep.equal(receiverCallbackData);
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const expectedFinalBalances = [
 | 
			
		||||
                expectedInitialBalances[0].minus(totalValuesTransferred[0]),
 | 
			
		||||
                expectedInitialBalances[1].plus(totalValuesTransferred[0]),
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should successfully transfer value and ignore extra assetData', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiverContract];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => {
 | 
			
		||||
                return value.times(valueMultiplier);
 | 
			
		||||
            });
 | 
			
		||||
            const extraData = '0102030405060708';
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverContractInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            const txReceipt = await erc1155ProxyWrapper.transferFromWithLogsAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiverContract,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
                extraData,
 | 
			
		||||
            );
 | 
			
		||||
            // check receiver log ignored extra asset data
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(2);
 | 
			
		||||
            const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs<
 | 
			
		||||
                DummyERC1155ReceiverBatchTokenReceivedEventArgs
 | 
			
		||||
            >;
 | 
			
		||||
            expect(receiverLog.args.operator).to.be.equal(erc1155Proxy.address);
 | 
			
		||||
            expect(receiverLog.args.from).to.be.equal(spender);
 | 
			
		||||
            expect(receiverLog.args.tokenIds.length).to.be.deep.equal(1);
 | 
			
		||||
            expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokensToTransfer[0]);
 | 
			
		||||
            expect(receiverLog.args.tokenValues.length).to.be.deep.equal(1);
 | 
			
		||||
            expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(totalValuesTransferred[0]);
 | 
			
		||||
            // note - if the `extraData` is ignored then the receiver log should ignore it as well.
 | 
			
		||||
            expect(receiverLog.args.data).to.be.deep.equal(receiverCallbackData);
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const expectedFinalBalances = [
 | 
			
		||||
                expectedInitialBalances[0].minus(totalValuesTransferred[0]),
 | 
			
		||||
                expectedInitialBalances[1].plus(totalValuesTransferred[0]),
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should transfer nothing if value is zero', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [new BigNumber(0)];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const expectedFinalBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should transfer nothing if value multiplier is zero', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = new BigNumber(0);
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const expectedFinalBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should transfer nothing if there are no tokens in asset data', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer: BigNumber[] = [];
 | 
			
		||||
            const valuesToTransfer: BigNumber[] = [];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                spender,
 | 
			
		||||
                receiver,
 | 
			
		||||
                erc1155Contract.address,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorized,
 | 
			
		||||
            );
 | 
			
		||||
            // check balances after transfer
 | 
			
		||||
            const expectedFinalBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
 | 
			
		||||
        });
 | 
			
		||||
        it('should propagate revert reason from erc1155 contract failure', async () => {
 | 
			
		||||
            // disable transfers
 | 
			
		||||
            const shouldRejectTransfer = true;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await erc1155Receiver.setRejectTransferFlag.sendTransactionAsync(shouldRejectTransfer),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiverContract];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverContractInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiverContract,
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    valueMultiplier,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    authorized,
 | 
			
		||||
                ),
 | 
			
		||||
                RevertReason.TransferRejected,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if transferring the same non-fungible token more than once', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const nftToTransfer = nonFungibleTokensOwnedBySpender[0];
 | 
			
		||||
            const tokensToTransfer = [nftToTransfer, nftToTransfer];
 | 
			
		||||
            const valuesToTransfer = [nonFungibleValueToTransfer, nonFungibleValueToTransfer];
 | 
			
		||||
            const valueMultiplier = valueMultiplierNft;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    valueMultiplier,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    authorized,
 | 
			
		||||
                ),
 | 
			
		||||
                RevertReason.NFTNotOwnedByFromAddress,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if there is a multiplication overflow', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 3);
 | 
			
		||||
            const maxUintValue = new BigNumber(2).pow(256).minus(1);
 | 
			
		||||
            const valuesToTransfer = [nonFungibleValueToTransfer, maxUintValue, nonFungibleValueToTransfer];
 | 
			
		||||
            const valueMultiplier = new BigNumber(2);
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            // note - this will overflow because we are trying to transfer `maxUintValue * 2` of the 2nd token
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    valueMultiplier,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    authorized,
 | 
			
		||||
                ),
 | 
			
		||||
                RevertReason.Uint256Overflow,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if transferring > 1 instances of a non-fungible token (valueMultiplier field >1)', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [nonFungibleValueToTransfer];
 | 
			
		||||
            const valueMultiplier = new BigNumber(2);
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    valueMultiplier,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    authorized,
 | 
			
		||||
                ),
 | 
			
		||||
                RevertReason.AmountEqualToOneRequired,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if transferring > 1 instances of a non-fungible token (`valuesToTransfer` field >1)', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = nonFungibleTokensOwnedBySpender.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [new BigNumber(2)];
 | 
			
		||||
            const valueMultiplier = valueMultiplierNft;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [
 | 
			
		||||
                // spender
 | 
			
		||||
                nftOwnerBalance,
 | 
			
		||||
                // receiver
 | 
			
		||||
                nftNotOwnerBalance,
 | 
			
		||||
            ];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    valueMultiplier,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    authorized,
 | 
			
		||||
                ),
 | 
			
		||||
                RevertReason.AmountEqualToOneRequired,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if sender balance is insufficient', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valueGreaterThanSpenderBalance = spenderInitialFungibleBalance.plus(1);
 | 
			
		||||
            const valuesToTransfer = [valueGreaterThanSpenderBalance];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    valueMultiplier,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    authorized,
 | 
			
		||||
                ),
 | 
			
		||||
                RevertReason.Uint256Underflow,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if sender allowance is insufficient', async () => {
 | 
			
		||||
            // dremove allowance for ERC1155 proxy
 | 
			
		||||
            const wrapper = erc1155ProxyWrapper.getContractWrapper(erc1155Contract.address);
 | 
			
		||||
            const isApproved = false;
 | 
			
		||||
            await wrapper.setApprovalForAllAsync(spender, erc1155Proxy.address, isApproved);
 | 
			
		||||
            const isApprovedActualValue = await wrapper.isApprovedForAllAsync(spender, erc1155Proxy.address);
 | 
			
		||||
            expect(isApprovedActualValue).to.be.equal(isApproved);
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    valueMultiplier,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    authorized,
 | 
			
		||||
                ),
 | 
			
		||||
                RevertReason.InsufficientAllowance,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should revert if caller is not authorized', async () => {
 | 
			
		||||
            // setup test parameters
 | 
			
		||||
            const tokenHolders = [spender, receiver];
 | 
			
		||||
            const tokensToTransfer = fungibleTokens.slice(0, 1);
 | 
			
		||||
            const valuesToTransfer = [fungibleValueToTransferLarge];
 | 
			
		||||
            const valueMultiplier = valueMultiplierSmall;
 | 
			
		||||
            // check balances before transfer
 | 
			
		||||
            const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
 | 
			
		||||
            await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
 | 
			
		||||
            // execute transfer
 | 
			
		||||
            await expectTransactionFailedAsync(
 | 
			
		||||
                erc1155ProxyWrapper.transferFromAsync(
 | 
			
		||||
                    spender,
 | 
			
		||||
                    receiver,
 | 
			
		||||
                    erc1155Contract.address,
 | 
			
		||||
                    tokensToTransfer,
 | 
			
		||||
                    valuesToTransfer,
 | 
			
		||||
                    valueMultiplier,
 | 
			
		||||
                    receiverCallbackData,
 | 
			
		||||
                    notAuthorized,
 | 
			
		||||
                ),
 | 
			
		||||
                RevertReason.SenderNotAuthorized,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
// tslint:enable:no-unnecessary-type-assertion
 | 
			
		||||
// tslint:disable:max-file-line-count
 | 
			
		||||
							
								
								
									
										383
									
								
								contracts/asset-proxy/test/utils/erc1155_proxy_wrapper.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										383
									
								
								contracts/asset-proxy/test/utils/erc1155_proxy_wrapper.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,383 @@
 | 
			
		||||
import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
 | 
			
		||||
import {
 | 
			
		||||
    constants,
 | 
			
		||||
    ERC1155FungibleHoldingsByOwner,
 | 
			
		||||
    ERC1155HoldingsByOwner,
 | 
			
		||||
    ERC1155NonFungibleHoldingsByOwner,
 | 
			
		||||
    LogDecoder,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { assetDataUtils } from '@0x/order-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
			
		||||
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts, ERC1155ProxyContract, IAssetProxyContract } from '../../src';
 | 
			
		||||
 | 
			
		||||
export class ERC1155ProxyWrapper {
 | 
			
		||||
    private readonly _tokenOwnerAddresses: string[];
 | 
			
		||||
    private readonly _fungibleTokenIds: string[];
 | 
			
		||||
    private readonly _nonFungibleTokenIds: string[];
 | 
			
		||||
    private readonly _nfts: Array<{ id: BigNumber; tokenId: BigNumber }>;
 | 
			
		||||
    private readonly _contractOwnerAddress: string;
 | 
			
		||||
    private readonly _web3Wrapper: Web3Wrapper;
 | 
			
		||||
    private readonly _provider: Provider;
 | 
			
		||||
    private readonly _logDecoder: LogDecoder;
 | 
			
		||||
    private readonly _dummyTokenWrappers: Erc1155Wrapper[];
 | 
			
		||||
    private readonly _assetProxyInterface: IAssetProxyContract;
 | 
			
		||||
    private _proxyContract?: ERC1155ProxyContract;
 | 
			
		||||
    private _proxyIdIfExists?: string;
 | 
			
		||||
    private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
 | 
			
		||||
 | 
			
		||||
    constructor(provider: Provider, tokenOwnerAddresses: string[], contractOwnerAddress: string) {
 | 
			
		||||
        this._web3Wrapper = new Web3Wrapper(provider);
 | 
			
		||||
        this._provider = provider;
 | 
			
		||||
        const allArtifacts = _.merge(artifacts, erc1155Artifacts);
 | 
			
		||||
        this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
 | 
			
		||||
        this._dummyTokenWrappers = [];
 | 
			
		||||
        this._assetProxyInterface = new IAssetProxyContract(
 | 
			
		||||
            artifacts.IAssetProxy.compilerOutput.abi,
 | 
			
		||||
            constants.NULL_ADDRESS,
 | 
			
		||||
            provider,
 | 
			
		||||
        );
 | 
			
		||||
        this._tokenOwnerAddresses = tokenOwnerAddresses;
 | 
			
		||||
        this._contractOwnerAddress = contractOwnerAddress;
 | 
			
		||||
        this._fungibleTokenIds = [];
 | 
			
		||||
        this._nonFungibleTokenIds = [];
 | 
			
		||||
        this._nfts = [];
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Deploys dummy ERC1155 contracts
 | 
			
		||||
     * @return An array of ERC1155 wrappers; one for each deployed contract.
 | 
			
		||||
     */
 | 
			
		||||
    public async deployDummyContractsAsync(): Promise<Erc1155Wrapper[]> {
 | 
			
		||||
        // tslint:disable-next-line:no-unused-variable
 | 
			
		||||
        for (const i of _.times(constants.NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY)) {
 | 
			
		||||
            const erc1155Contract = await ERC1155MintableContract.deployFrom0xArtifactAsync(
 | 
			
		||||
                erc1155Artifacts.ERC1155Mintable,
 | 
			
		||||
                this._provider,
 | 
			
		||||
                txDefaults,
 | 
			
		||||
            );
 | 
			
		||||
            const erc1155Wrapper = new Erc1155Wrapper(erc1155Contract, this._provider, this._contractOwnerAddress);
 | 
			
		||||
            this._dummyTokenWrappers.push(erc1155Wrapper);
 | 
			
		||||
        }
 | 
			
		||||
        return this._dummyTokenWrappers;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Deploys the ERC1155 proxy
 | 
			
		||||
     * @return Deployed ERC1155 proxy contract instance
 | 
			
		||||
     */
 | 
			
		||||
    public async deployProxyAsync(): Promise<ERC1155ProxyContract> {
 | 
			
		||||
        this._proxyContract = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.ERC1155Proxy,
 | 
			
		||||
            this._provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
        );
 | 
			
		||||
        this._proxyIdIfExists = await this._proxyContract.getProxyId.callAsync();
 | 
			
		||||
        return this._proxyContract;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Gets the ERC1155 proxy id
 | 
			
		||||
     */
 | 
			
		||||
    public getProxyId(): string {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        return this._proxyIdIfExists as string;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev transfers erc1155 fungible/non-fungible tokens.
 | 
			
		||||
     * @param from source address
 | 
			
		||||
     * @param to destination address
 | 
			
		||||
     * @param contractAddress address of erc155 contract
 | 
			
		||||
     * @param tokensToTransfer array of erc1155 tokens to transfer
 | 
			
		||||
     * @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
 | 
			
		||||
     * @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
 | 
			
		||||
     * @param receiverCallbackData callback data if `to` is a contract
 | 
			
		||||
     * @param authorizedSender sender of `transferFrom` transaction
 | 
			
		||||
     * @param extraData extra data to append to `transferFrom` transaction. Optional.
 | 
			
		||||
     * @return tranasction hash.
 | 
			
		||||
     */
 | 
			
		||||
    public async transferFromAsync(
 | 
			
		||||
        from: string,
 | 
			
		||||
        to: string,
 | 
			
		||||
        contractAddress: string,
 | 
			
		||||
        tokensToTransfer: BigNumber[],
 | 
			
		||||
        valuesToTransfer: BigNumber[],
 | 
			
		||||
        valueMultiplier: BigNumber,
 | 
			
		||||
        receiverCallbackData: string,
 | 
			
		||||
        authorizedSender: string,
 | 
			
		||||
        extraData?: string,
 | 
			
		||||
    ): Promise<string> {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        let encodedAssetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
            contractAddress,
 | 
			
		||||
            tokensToTransfer,
 | 
			
		||||
            valuesToTransfer,
 | 
			
		||||
            receiverCallbackData,
 | 
			
		||||
        );
 | 
			
		||||
        if (!_.isUndefined(extraData)) {
 | 
			
		||||
            encodedAssetData = `${encodedAssetData}${extraData}`;
 | 
			
		||||
        }
 | 
			
		||||
        const data = this._assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
			
		||||
            encodedAssetData,
 | 
			
		||||
            from,
 | 
			
		||||
            to,
 | 
			
		||||
            valueMultiplier,
 | 
			
		||||
        );
 | 
			
		||||
        const txHash = await this._web3Wrapper.sendTransactionAsync({
 | 
			
		||||
            to: (this._proxyContract as ERC1155ProxyContract).address,
 | 
			
		||||
            data,
 | 
			
		||||
            from: authorizedSender,
 | 
			
		||||
        });
 | 
			
		||||
        return txHash;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev transfers erc1155 fungible/non-fungible tokens.
 | 
			
		||||
     * @param from source address
 | 
			
		||||
     * @param to destination address
 | 
			
		||||
     * @param contractAddress address of erc155 contract
 | 
			
		||||
     * @param tokensToTransfer array of erc1155 tokens to transfer
 | 
			
		||||
     * @param valuesToTransfer array of corresponding values for each erc1155 token to transfer
 | 
			
		||||
     * @param valueMultiplier each value in `valuesToTransfer` is multiplied by this
 | 
			
		||||
     * @param receiverCallbackData callback data if `to` is a contract
 | 
			
		||||
     * @param authorizedSender sender of `transferFrom` transaction
 | 
			
		||||
     * @param extraData extra data to append to `transferFrom` transaction. Optional.
 | 
			
		||||
     * @return tranasction receipt with decoded logs.
 | 
			
		||||
     */
 | 
			
		||||
    public async transferFromWithLogsAsync(
 | 
			
		||||
        from: string,
 | 
			
		||||
        to: string,
 | 
			
		||||
        contractAddress: string,
 | 
			
		||||
        tokensToTransfer: BigNumber[],
 | 
			
		||||
        valuesToTransfer: BigNumber[],
 | 
			
		||||
        valueMultiplier: BigNumber,
 | 
			
		||||
        receiverCallbackData: string,
 | 
			
		||||
        authorizedSender: string,
 | 
			
		||||
        extraData?: string,
 | 
			
		||||
    ): Promise<TransactionReceiptWithDecodedLogs> {
 | 
			
		||||
        const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
			
		||||
            await this.transferFromAsync(
 | 
			
		||||
                from,
 | 
			
		||||
                to,
 | 
			
		||||
                contractAddress,
 | 
			
		||||
                tokensToTransfer,
 | 
			
		||||
                valuesToTransfer,
 | 
			
		||||
                valueMultiplier,
 | 
			
		||||
                receiverCallbackData,
 | 
			
		||||
                authorizedSender,
 | 
			
		||||
                extraData,
 | 
			
		||||
            ),
 | 
			
		||||
        );
 | 
			
		||||
        return txReceipt;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev For each deployed ERC1155 contract, this function mints a set of fungible/non-fungible
 | 
			
		||||
     *      tokens for each token owner address (`_tokenOwnerAddresses`).
 | 
			
		||||
     * @return Balances of each token owner, across all ERC1155 contracts and tokens.
 | 
			
		||||
     */
 | 
			
		||||
    public async setBalancesAndAllowancesAsync(): Promise<ERC1155HoldingsByOwner> {
 | 
			
		||||
        this._validateDummyTokenContractsExistOrThrow();
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        this._initialTokenIdsByOwner = {
 | 
			
		||||
            fungible: {},
 | 
			
		||||
            nonFungible: {},
 | 
			
		||||
        };
 | 
			
		||||
        const fungibleHoldingsByOwner: ERC1155FungibleHoldingsByOwner = {};
 | 
			
		||||
        const nonFungibleHoldingsByOwner: ERC1155NonFungibleHoldingsByOwner = {};
 | 
			
		||||
        // Set balances accordingly
 | 
			
		||||
        for (const dummyWrapper of this._dummyTokenWrappers) {
 | 
			
		||||
            const dummyAddress = dummyWrapper.getContract().address;
 | 
			
		||||
            // tslint:disable-next-line:no-unused-variable
 | 
			
		||||
            for (const i of _.times(constants.NUM_ERC1155_FUNGIBLE_TOKENS_MINT)) {
 | 
			
		||||
                // Create a fungible token
 | 
			
		||||
                const tokenId = await dummyWrapper.mintFungibleTokensAsync(
 | 
			
		||||
                    this._tokenOwnerAddresses,
 | 
			
		||||
                    constants.INITIAL_ERC1155_FUNGIBLE_BALANCE,
 | 
			
		||||
                );
 | 
			
		||||
                const tokenIdAsString = tokenId.toString();
 | 
			
		||||
                this._fungibleTokenIds.push(tokenIdAsString);
 | 
			
		||||
                // Mint tokens for each owner for this token
 | 
			
		||||
                for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
 | 
			
		||||
                    // tslint:disable-next-line:no-unused-variable
 | 
			
		||||
                    if (_.isUndefined(fungibleHoldingsByOwner[tokenOwnerAddress])) {
 | 
			
		||||
                        fungibleHoldingsByOwner[tokenOwnerAddress] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                    if (_.isUndefined(fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress])) {
 | 
			
		||||
                        fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                    fungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString] =
 | 
			
		||||
                        constants.INITIAL_ERC1155_FUNGIBLE_BALANCE;
 | 
			
		||||
                    await dummyWrapper.setApprovalForAllAsync(
 | 
			
		||||
                        tokenOwnerAddress,
 | 
			
		||||
                        (this._proxyContract as ERC1155ProxyContract).address,
 | 
			
		||||
                        true,
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            // Non-fungible tokens
 | 
			
		||||
            // tslint:disable-next-line:no-unused-variable
 | 
			
		||||
            for (const j of _.times(constants.NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT)) {
 | 
			
		||||
                const [tokenId, nftIds] = await dummyWrapper.mintNonFungibleTokensAsync(this._tokenOwnerAddresses);
 | 
			
		||||
                const tokenIdAsString = tokenId.toString();
 | 
			
		||||
                this._nonFungibleTokenIds.push(tokenIdAsString);
 | 
			
		||||
                _.each(this._tokenOwnerAddresses, async (tokenOwnerAddress: string, i: number) => {
 | 
			
		||||
                    if (_.isUndefined(nonFungibleHoldingsByOwner[tokenOwnerAddress])) {
 | 
			
		||||
                        nonFungibleHoldingsByOwner[tokenOwnerAddress] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                    if (_.isUndefined(nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress])) {
 | 
			
		||||
                        nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                    if (_.isUndefined(nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString])) {
 | 
			
		||||
                        nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString] = [];
 | 
			
		||||
                    }
 | 
			
		||||
                    this._nfts.push({ id: nftIds[i], tokenId });
 | 
			
		||||
                    nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyAddress][tokenIdAsString].push(nftIds[i]);
 | 
			
		||||
                    await dummyWrapper.setApprovalForAllAsync(
 | 
			
		||||
                        tokenOwnerAddress,
 | 
			
		||||
                        (this._proxyContract as ERC1155ProxyContract).address,
 | 
			
		||||
                        true,
 | 
			
		||||
                    );
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        this._initialTokenIdsByOwner = {
 | 
			
		||||
            fungible: fungibleHoldingsByOwner,
 | 
			
		||||
            nonFungible: nonFungibleHoldingsByOwner,
 | 
			
		||||
        };
 | 
			
		||||
        return this._initialTokenIdsByOwner;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev For each deployed ERC1155 contract, this function quieries the set of fungible/non-fungible
 | 
			
		||||
     *      tokens for each token owner address (`_tokenOwnerAddresses`).
 | 
			
		||||
     * @return Balances of each token owner, across all ERC1155 contracts and tokens.
 | 
			
		||||
     */
 | 
			
		||||
    public async getBalancesAsync(): Promise<ERC1155HoldingsByOwner> {
 | 
			
		||||
        this._validateDummyTokenContractsExistOrThrow();
 | 
			
		||||
        this._validateBalancesAndAllowancesSetOrThrow();
 | 
			
		||||
        const tokenHoldingsByOwner: ERC1155FungibleHoldingsByOwner = {};
 | 
			
		||||
        const nonFungibleHoldingsByOwner: ERC1155NonFungibleHoldingsByOwner = {};
 | 
			
		||||
        for (const dummyTokenWrapper of this._dummyTokenWrappers) {
 | 
			
		||||
            const tokenContract = dummyTokenWrapper.getContract();
 | 
			
		||||
            const tokenAddress = tokenContract.address;
 | 
			
		||||
            // Construct batch balance call
 | 
			
		||||
            const tokenOwners: string[] = [];
 | 
			
		||||
            const tokenIds: BigNumber[] = [];
 | 
			
		||||
            for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
 | 
			
		||||
                for (const tokenId of this._fungibleTokenIds) {
 | 
			
		||||
                    tokenOwners.push(tokenOwnerAddress);
 | 
			
		||||
                    tokenIds.push(new BigNumber(tokenId));
 | 
			
		||||
                }
 | 
			
		||||
                for (const nft of this._nfts) {
 | 
			
		||||
                    tokenOwners.push(tokenOwnerAddress);
 | 
			
		||||
                    tokenIds.push(nft.id);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            const balances = await dummyTokenWrapper.getBalancesAsync(tokenOwners, tokenIds);
 | 
			
		||||
            // Parse out balances into fungible / non-fungible token holdings
 | 
			
		||||
            let i = 0;
 | 
			
		||||
            for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
 | 
			
		||||
                // Fungible tokens
 | 
			
		||||
                for (const tokenId of this._fungibleTokenIds) {
 | 
			
		||||
                    if (_.isUndefined(tokenHoldingsByOwner[tokenOwnerAddress])) {
 | 
			
		||||
                        tokenHoldingsByOwner[tokenOwnerAddress] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                    if (_.isUndefined(tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress])) {
 | 
			
		||||
                        tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                    tokenHoldingsByOwner[tokenOwnerAddress][tokenAddress][tokenId] = balances[i++];
 | 
			
		||||
                }
 | 
			
		||||
                // Non-fungible tokens
 | 
			
		||||
                for (const nft of this._nfts) {
 | 
			
		||||
                    if (_.isUndefined(nonFungibleHoldingsByOwner[tokenOwnerAddress])) {
 | 
			
		||||
                        nonFungibleHoldingsByOwner[tokenOwnerAddress] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                    if (_.isUndefined(nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress])) {
 | 
			
		||||
                        nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                    if (
 | 
			
		||||
                        _.isUndefined(
 | 
			
		||||
                            nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()],
 | 
			
		||||
                        )
 | 
			
		||||
                    ) {
 | 
			
		||||
                        nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()] = [];
 | 
			
		||||
                    }
 | 
			
		||||
                    const isOwner = balances[i++];
 | 
			
		||||
                    if (isOwner.isEqualTo(1)) {
 | 
			
		||||
                        nonFungibleHoldingsByOwner[tokenOwnerAddress][tokenAddress][nft.tokenId.toString()].push(
 | 
			
		||||
                            nft.id,
 | 
			
		||||
                        );
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        const holdingsByOwner = {
 | 
			
		||||
            fungible: tokenHoldingsByOwner,
 | 
			
		||||
            nonFungible: nonFungibleHoldingsByOwner,
 | 
			
		||||
        };
 | 
			
		||||
        return holdingsByOwner;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * @dev Checks if proxy is approved to transfer tokens on behalf of `userAddress`.
 | 
			
		||||
     * @param userAddress owner of ERC1155 tokens.
 | 
			
		||||
     * @param contractAddress address of ERC1155 contract.
 | 
			
		||||
     * @return True iff the proxy is approved for all. False otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    public async isProxyApprovedForAllAsync(userAddress: string, contractAddress: string): Promise<boolean> {
 | 
			
		||||
        this._validateProxyContractExistsOrThrow();
 | 
			
		||||
        const tokenContract = this._getContractFromAddress(contractAddress);
 | 
			
		||||
        const operator = (this._proxyContract as ERC1155ProxyContract).address;
 | 
			
		||||
        const didApproveAll = await tokenContract.isApprovedForAll.callAsync(userAddress, operator);
 | 
			
		||||
        return didApproveAll;
 | 
			
		||||
    }
 | 
			
		||||
    public getFungibleTokenIds(): BigNumber[] {
 | 
			
		||||
        const fungibleTokenIds = _.map(this._fungibleTokenIds, (tokenIdAsString: string) => {
 | 
			
		||||
            return new BigNumber(tokenIdAsString);
 | 
			
		||||
        });
 | 
			
		||||
        return fungibleTokenIds;
 | 
			
		||||
    }
 | 
			
		||||
    public getNonFungibleTokenIds(): BigNumber[] {
 | 
			
		||||
        const nonFungibleTokenIds = _.map(this._nonFungibleTokenIds, (tokenIdAsString: string) => {
 | 
			
		||||
            return new BigNumber(tokenIdAsString);
 | 
			
		||||
        });
 | 
			
		||||
        return nonFungibleTokenIds;
 | 
			
		||||
    }
 | 
			
		||||
    public getTokenOwnerAddresses(): string[] {
 | 
			
		||||
        return this._tokenOwnerAddresses;
 | 
			
		||||
    }
 | 
			
		||||
    public getContractWrapper(contractAddress: string): Erc1155Wrapper {
 | 
			
		||||
        const tokenWrapper = _.find(this._dummyTokenWrappers, (wrapper: Erc1155Wrapper) => {
 | 
			
		||||
            return wrapper.getContract().address === contractAddress;
 | 
			
		||||
        });
 | 
			
		||||
        if (_.isUndefined(tokenWrapper)) {
 | 
			
		||||
            throw new Error(`Contract: ${contractAddress} was not deployed through ERC1155ProxyWrapper`);
 | 
			
		||||
        }
 | 
			
		||||
        return tokenWrapper;
 | 
			
		||||
    }
 | 
			
		||||
    private _getContractFromAddress(tokenAddress: string): ERC1155MintableContract {
 | 
			
		||||
        const tokenContractIfExists = _.find(this._dummyTokenWrappers, c => c.getContract().address === tokenAddress);
 | 
			
		||||
        if (_.isUndefined(tokenContractIfExists)) {
 | 
			
		||||
            throw new Error(`Token: ${tokenAddress} was not deployed through ERC1155ProxyWrapper`);
 | 
			
		||||
        }
 | 
			
		||||
        return tokenContractIfExists.getContract();
 | 
			
		||||
    }
 | 
			
		||||
    private _validateDummyTokenContractsExistOrThrow(): void {
 | 
			
		||||
        if (_.isUndefined(this._dummyTokenWrappers)) {
 | 
			
		||||
            throw new Error('Dummy ERC1155 tokens not yet deployed, please call "deployDummyTokensAsync"');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private _validateProxyContractExistsOrThrow(): void {
 | 
			
		||||
        if (_.isUndefined(this._proxyContract)) {
 | 
			
		||||
            throw new Error('ERC1155 proxy contract not yet deployed, please call "deployProxyAsync"');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private _validateBalancesAndAllowancesSetOrThrow(): void {
 | 
			
		||||
        if (
 | 
			
		||||
            _.keys(this._initialTokenIdsByOwner.fungible).length === 0 ||
 | 
			
		||||
            _.keys(this._initialTokenIdsByOwner.nonFungible).length === 0
 | 
			
		||||
        ) {
 | 
			
		||||
            throw new Error(
 | 
			
		||||
                'Dummy ERC1155 balances and allowances not yet set, please call "setBalancesAndAllowancesAsync"',
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,2 +1,3 @@
 | 
			
		||||
export * from './erc20_wrapper';
 | 
			
		||||
export * from './erc721_wrapper';
 | 
			
		||||
export * from './erc1155_proxy_wrapper';
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
			
		||||
    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
			
		||||
    "files": [
 | 
			
		||||
        "generated-artifacts/ERC1155Proxy.json",
 | 
			
		||||
        "generated-artifacts/ERC20Proxy.json",
 | 
			
		||||
        "generated-artifacts/ERC721Proxy.json",
 | 
			
		||||
        "generated-artifacts/IAssetData.json",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.1.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added ERC1155Proxy test constants and interfaces",
 | 
			
		||||
                "pr": 1661
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "3.0.9",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -38,11 +38,16 @@ export const constants = {
 | 
			
		||||
    NUM_DUMMY_ERC20_TO_DEPLOY: 3,
 | 
			
		||||
    NUM_DUMMY_ERC721_TO_DEPLOY: 2,
 | 
			
		||||
    NUM_ERC721_TOKENS_TO_MINT: 2,
 | 
			
		||||
    NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY: 1,
 | 
			
		||||
    NUM_ERC1155_FUNGIBLE_TOKENS_MINT: 3,
 | 
			
		||||
    NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT: 3,
 | 
			
		||||
    NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
 | 
			
		||||
    UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
 | 
			
		||||
    TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)),
 | 
			
		||||
    INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
 | 
			
		||||
    INITIAL_ERC20_ALLOWANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
 | 
			
		||||
    INITIAL_ERC1155_FUNGIBLE_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
 | 
			
		||||
    INITIAL_ERC1155_FUNGIBLE_ALLOWANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
 | 
			
		||||
    STATIC_ORDER_PARAMS: {
 | 
			
		||||
        makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
 | 
			
		||||
        takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,9 @@ export {
 | 
			
		||||
    MarketBuyOrders,
 | 
			
		||||
    MarketSellOrders,
 | 
			
		||||
    ERC721TokenIdsByOwner,
 | 
			
		||||
    ERC1155FungibleHoldingsByOwner,
 | 
			
		||||
    ERC1155NonFungibleHoldingsByOwner,
 | 
			
		||||
    ERC1155HoldingsByOwner,
 | 
			
		||||
    OrderStatus,
 | 
			
		||||
    AllowanceAmountScenario,
 | 
			
		||||
    AssetDataScenario,
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,27 @@ export interface ERC721TokenIdsByOwner {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ERC1155FungibleHoldingsByOwner {
 | 
			
		||||
    [ownerAddress: string]: {
 | 
			
		||||
        [tokenAddress: string]: {
 | 
			
		||||
            [tokenId: string]: BigNumber;
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ERC1155NonFungibleHoldingsByOwner {
 | 
			
		||||
    [ownerAddress: string]: {
 | 
			
		||||
        [tokenAddress: string]: {
 | 
			
		||||
            [tokenId: string]: BigNumber[];
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ERC1155HoldingsByOwner {
 | 
			
		||||
    fungible: ERC1155FungibleHoldingsByOwner;
 | 
			
		||||
    nonFungible: ERC1155NonFungibleHoldingsByOwner;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface SubmissionContractEventArgs {
 | 
			
		||||
    transactionId: BigNumber;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -91,6 +91,8 @@ export {
 | 
			
		||||
    SingleAssetData,
 | 
			
		||||
    ERC20AssetData,
 | 
			
		||||
    ERC721AssetData,
 | 
			
		||||
    ERC1155AssetData,
 | 
			
		||||
    ERC1155AssetDataAbi,
 | 
			
		||||
    MultiAssetData,
 | 
			
		||||
    MultiAssetDataWithRecursiveDecoding,
 | 
			
		||||
    SignatureType,
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,7 @@ export {
 | 
			
		||||
    AssetData,
 | 
			
		||||
    ERC20AssetData,
 | 
			
		||||
    ERC721AssetData,
 | 
			
		||||
    ERC1155AssetData,
 | 
			
		||||
    SingleAssetData,
 | 
			
		||||
    MultiAssetData,
 | 
			
		||||
    MultiAssetDataWithRecursiveDecoding,
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add Coordinator EIP712 constants",
 | 
			
		||||
                "pr": 1705
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added encoding/decoding fdor ERC1155 asset data",
 | 
			
		||||
                "pr": 1661
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
import {
 | 
			
		||||
    AssetProxyId,
 | 
			
		||||
    ERC1155AssetData,
 | 
			
		||||
    ERC1155AssetDataAbi,
 | 
			
		||||
    ERC1155AssetDataNoProxyId,
 | 
			
		||||
    ERC20AssetData,
 | 
			
		||||
    ERC721AssetData,
 | 
			
		||||
    MultiAssetData,
 | 
			
		||||
@@ -73,6 +76,47 @@ export const assetDataUtils = {
 | 
			
		||||
            tokenId: (decodedAssetData as any).tokenId,
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Encodes a set of ERC1155 assets into an assetData string, usable in the makerAssetData or
 | 
			
		||||
     * takerAssetData fields of a 0x order.
 | 
			
		||||
     * @param tokenAddress The token address of the ERC1155 contract
 | 
			
		||||
     * @param tokenIds The Id's of the ERC1155 tokens to transfer
 | 
			
		||||
     * @param tokenValues The values of each respective token Id to transfer
 | 
			
		||||
     * @param callbackData The data forwarded to a receiver, if receiver is a contract.
 | 
			
		||||
     * @return The hex encoded assetData string
 | 
			
		||||
     */
 | 
			
		||||
    encodeERC1155AssetData(
 | 
			
		||||
        tokenAddress: string,
 | 
			
		||||
        tokenIds: BigNumber[],
 | 
			
		||||
        tokenValues: BigNumber[],
 | 
			
		||||
        callbackData: string,
 | 
			
		||||
    ): string {
 | 
			
		||||
        const abiEncoder = AbiEncoder.createMethod('ERC1155Token', ERC1155AssetDataAbi);
 | 
			
		||||
        const args = [tokenAddress, tokenIds, tokenValues, callbackData];
 | 
			
		||||
        const assetData = abiEncoder.encode(args, encodingRules);
 | 
			
		||||
        return assetData;
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Decodes an ERC1155 assetData hex string into it's corresponding ERC1155 components.
 | 
			
		||||
     * @param assetData Hex encoded assetData string to decode
 | 
			
		||||
     * @return An object containing the decoded tokenAddress, tokenIds, tokenValues, callbackData & assetProxyId
 | 
			
		||||
     */
 | 
			
		||||
    decodeERC1155AssetData(assetData: string): ERC1155AssetData {
 | 
			
		||||
        const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
 | 
			
		||||
        if (assetProxyId !== AssetProxyId.ERC1155) {
 | 
			
		||||
            throw new Error(`Invalid assetProxyId. Expected '${AssetProxyId.ERC1155}', got '${assetProxyId}'`);
 | 
			
		||||
        }
 | 
			
		||||
        const abiEncoder = AbiEncoder.createMethod('ERC1155Token', ERC1155AssetDataAbi);
 | 
			
		||||
        // tslint:disable-next-line:no-unnecessary-type-assertion
 | 
			
		||||
        const decodedAssetData = abiEncoder.decode(assetData, decodingRules) as ERC1155AssetDataNoProxyId;
 | 
			
		||||
        return {
 | 
			
		||||
            assetProxyId,
 | 
			
		||||
            tokenAddress: decodedAssetData.tokenAddress,
 | 
			
		||||
            tokenIds: decodedAssetData.tokenIds,
 | 
			
		||||
            tokenValues: decodedAssetData.tokenValues,
 | 
			
		||||
            callbackData: decodedAssetData.callbackData,
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Encodes assetData for multiple AssetProxies into a single hex encoded assetData string, usable in the makerAssetData or
 | 
			
		||||
     * takerAssetData fields in a 0x order.
 | 
			
		||||
@@ -174,6 +218,7 @@ export const assetDataUtils = {
 | 
			
		||||
        if (
 | 
			
		||||
            assetProxyId !== AssetProxyId.ERC20 &&
 | 
			
		||||
            assetProxyId !== AssetProxyId.ERC721 &&
 | 
			
		||||
            assetProxyId !== AssetProxyId.ERC1155 &&
 | 
			
		||||
            assetProxyId !== AssetProxyId.MultiAsset
 | 
			
		||||
        ) {
 | 
			
		||||
            throw new Error(`Invalid assetProxyId: ${assetProxyId}`);
 | 
			
		||||
@@ -194,6 +239,13 @@ export const assetDataUtils = {
 | 
			
		||||
    isERC721AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC721AssetData {
 | 
			
		||||
        return decodedAssetData.assetProxyId === AssetProxyId.ERC721;
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if the decoded asset data is valid ERC1155 data
 | 
			
		||||
     * @param decodedAssetData The decoded asset data to check
 | 
			
		||||
     */
 | 
			
		||||
    isERC1155AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC1155AssetData {
 | 
			
		||||
        return decodedAssetData.assetProxyId === AssetProxyId.ERC1155;
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if the decoded asset data is valid MultiAsset data
 | 
			
		||||
     * @param decodedAssetData The decoded asset data to check
 | 
			
		||||
@@ -243,6 +295,14 @@ export const assetDataUtils = {
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Throws if the assetData is not ERC1155.
 | 
			
		||||
     * @param assetData Hex encoded assetData string
 | 
			
		||||
     */
 | 
			
		||||
    assertIsERC1155AssetData(assetData: string): void {
 | 
			
		||||
        // If the asset data is correctly decoded then it is valid.
 | 
			
		||||
        assetDataUtils.decodeERC1155AssetData(assetData);
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * Throws if the length or assetProxyId are invalid for the MultiAssetProxy.
 | 
			
		||||
     * @param assetData Hex encoded assetData string
 | 
			
		||||
@@ -277,6 +337,9 @@ export const assetDataUtils = {
 | 
			
		||||
            case AssetProxyId.ERC721:
 | 
			
		||||
                assetDataUtils.assertIsERC721AssetData(assetData);
 | 
			
		||||
                break;
 | 
			
		||||
            case AssetProxyId.ERC1155:
 | 
			
		||||
                assetDataUtils.assertIsERC1155AssetData(assetData);
 | 
			
		||||
                break;
 | 
			
		||||
            case AssetProxyId.MultiAsset:
 | 
			
		||||
                assetDataUtils.assertIsMultiAssetData(assetData);
 | 
			
		||||
                break;
 | 
			
		||||
@@ -287,7 +350,7 @@ export const assetDataUtils = {
 | 
			
		||||
    /**
 | 
			
		||||
     * Decode any assetData into it's corresponding assetData object
 | 
			
		||||
     * @param assetData Hex encoded assetData string to decode
 | 
			
		||||
     * @return Either a ERC20 or ERC721 assetData object
 | 
			
		||||
     * @return Either a ERC20, ERC721, ERC1155, or MultiAsset assetData object
 | 
			
		||||
     */
 | 
			
		||||
    decodeAssetDataOrThrow(assetData: string): SingleAssetData | MultiAssetData {
 | 
			
		||||
        const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
 | 
			
		||||
@@ -298,6 +361,9 @@ export const assetDataUtils = {
 | 
			
		||||
            case AssetProxyId.ERC721:
 | 
			
		||||
                const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData);
 | 
			
		||||
                return erc721AssetData;
 | 
			
		||||
            case AssetProxyId.ERC1155:
 | 
			
		||||
                const erc1155AssetData = assetDataUtils.decodeERC1155AssetData(assetData);
 | 
			
		||||
                return erc1155AssetData;
 | 
			
		||||
            case AssetProxyId.MultiAsset:
 | 
			
		||||
                const multiAssetData = assetDataUtils.decodeMultiAssetData(assetData);
 | 
			
		||||
                return multiAssetData;
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,8 @@ export {
 | 
			
		||||
    SingleAssetData,
 | 
			
		||||
    ERC20AssetData,
 | 
			
		||||
    ERC721AssetData,
 | 
			
		||||
    ERC1155AssetData,
 | 
			
		||||
    ERC1155AssetDataAbi,
 | 
			
		||||
    MultiAssetData,
 | 
			
		||||
    MultiAssetDataWithRecursiveDecoding,
 | 
			
		||||
    AssetProxyId,
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,15 @@ const KNOWN_ERC721_ENCODING = {
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_ERC1155_ENCODING = {
 | 
			
		||||
    tokenAddress: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
 | 
			
		||||
    tokenIds: [new BigNumber(100), new BigNumber(1001), new BigNumber(10001)],
 | 
			
		||||
    tokenValues: [new BigNumber(200), new BigNumber(2001), new BigNumber(20001)],
 | 
			
		||||
    callbackData:
 | 
			
		||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
			
		||||
    assetData:
 | 
			
		||||
        '0x9645780d0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
 | 
			
		||||
};
 | 
			
		||||
const KNOWN_MULTI_ASSET_ENCODING = {
 | 
			
		||||
    amounts: [new BigNumber(1), new BigNumber(1)],
 | 
			
		||||
    nestedAssetData: [KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC721_ENCODING.assetData],
 | 
			
		||||
@@ -50,6 +59,23 @@ describe('assetDataUtils', () => {
 | 
			
		||||
        expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.ERC721);
 | 
			
		||||
        expect(decodedAssetData.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId);
 | 
			
		||||
    });
 | 
			
		||||
    it('should encode ERC1155', () => {
 | 
			
		||||
        const assetData = assetDataUtils.encodeERC1155AssetData(
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenAddress,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenIds,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.tokenValues,
 | 
			
		||||
            KNOWN_ERC1155_ENCODING.callbackData,
 | 
			
		||||
        );
 | 
			
		||||
        expect(assetData).to.equal(KNOWN_ERC1155_ENCODING.assetData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should decode ERC1155', () => {
 | 
			
		||||
        const decodedAssetData = assetDataUtils.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData);
 | 
			
		||||
        expect(decodedAssetData.assetProxyId).to.be.equal(AssetProxyId.ERC1155);
 | 
			
		||||
        expect(decodedAssetData.tokenAddress).to.be.equal(KNOWN_ERC1155_ENCODING.tokenAddress);
 | 
			
		||||
        expect(decodedAssetData.tokenValues).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenValues);
 | 
			
		||||
        expect(decodedAssetData.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds);
 | 
			
		||||
        expect(decodedAssetData.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData);
 | 
			
		||||
    });
 | 
			
		||||
    it('should encode ERC20 and ERC721 multiAssetData', () => {
 | 
			
		||||
        const assetData = assetDataUtils.encodeMultiAssetData(
 | 
			
		||||
            KNOWN_MULTI_ASSET_ENCODING.amounts,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,17 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.2.2",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added ERC1155 revert reasons",
 | 
			
		||||
                "pr": 1657
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Added `ERC1155AssetData`, `ERC1155AssetDataNoProxyId`, and `ERC1155AssetDataAbi`",
 | 
			
		||||
                "pr": 1661
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "2.2.1",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -163,6 +163,7 @@ export enum AssetProxyId {
 | 
			
		||||
    ERC20 = '0xf47261b0',
 | 
			
		||||
    ERC721 = '0x02571792',
 | 
			
		||||
    MultiAsset = '0x94cfcdd7',
 | 
			
		||||
    ERC1155 = '0x9645780d',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ERC20AssetData {
 | 
			
		||||
@@ -176,7 +177,29 @@ export interface ERC721AssetData {
 | 
			
		||||
    tokenId: BigNumber;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type SingleAssetData = ERC20AssetData | ERC721AssetData;
 | 
			
		||||
export interface ERC1155AssetData {
 | 
			
		||||
    assetProxyId: string;
 | 
			
		||||
    tokenAddress: string;
 | 
			
		||||
    tokenIds: BigNumber[];
 | 
			
		||||
    tokenValues: BigNumber[];
 | 
			
		||||
    callbackData: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ERC1155AssetDataNoProxyId {
 | 
			
		||||
    tokenAddress: string;
 | 
			
		||||
    tokenValues: BigNumber[];
 | 
			
		||||
    tokenIds: BigNumber[];
 | 
			
		||||
    callbackData: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const ERC1155AssetDataAbi = [
 | 
			
		||||
    { name: 'tokenAddress', type: 'address' },
 | 
			
		||||
    { name: 'tokenIds', type: 'uint256[]' },
 | 
			
		||||
    { name: 'tokenValues', type: 'uint256[]' },
 | 
			
		||||
    { name: 'callbackData', type: 'bytes' },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export type SingleAssetData = ERC20AssetData | ERC721AssetData | ERC1155AssetData;
 | 
			
		||||
 | 
			
		||||
export interface MultiAssetData {
 | 
			
		||||
    assetProxyId: string;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								yarn.lock
									
									
									
									
									
								
							@@ -11371,9 +11371,8 @@ nan@2.10.0, nan@>=2.5.1, nan@^2.0.8, nan@^2.2.1, nan@^2.3.0, nan@^2.3.3, nan@^2.
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
 | 
			
		||||
 | 
			
		||||
nan@^2.11.0:
 | 
			
		||||
  version "2.13.1"
 | 
			
		||||
  resolved "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz#a15bee3790bde247e8f38f1d446edcdaeb05f2dd"
 | 
			
		||||
  integrity sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==
 | 
			
		||||
  version "2.12.1"
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
 | 
			
		||||
 | 
			
		||||
nano-json-stream-parser@^0.1.2:
 | 
			
		||||
  version "0.1.2"
 | 
			
		||||
@@ -13564,6 +13563,8 @@ react-highlight@0xproject/react-highlight#react-peer-deps:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    highlight.js "^9.11.0"
 | 
			
		||||
    highlightjs-solidity "^1.0.5"
 | 
			
		||||
    react "^16.4.2"
 | 
			
		||||
    react-dom "^16.4.2"
 | 
			
		||||
 | 
			
		||||
react-hot-loader@^4.3.3:
 | 
			
		||||
  version "4.3.4"
 | 
			
		||||
@@ -17653,8 +17654,7 @@ websocket@1.0.26:
 | 
			
		||||
 | 
			
		||||
websocket@^1.0.26:
 | 
			
		||||
  version "1.0.28"
 | 
			
		||||
  resolved "https://registry.npmjs.org/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3"
 | 
			
		||||
  integrity sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA==
 | 
			
		||||
  resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3"
 | 
			
		||||
  dependencies:
 | 
			
		||||
    debug "^2.2.0"
 | 
			
		||||
    nan "^2.11.0"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user