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",
 | 
					                "note": "Do not reexport external dependencies",
 | 
				
			||||||
                "pr": 1682
 | 
					                "pr": 1682
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "note": "Add ERC1155Proxy",
 | 
				
			||||||
 | 
					                "pr": 1661
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,7 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "contracts": [
 | 
					    "contracts": [
 | 
				
			||||||
 | 
					        "src/ERC1155Proxy.sol",
 | 
				
			||||||
        "src/ERC20Proxy.sol",
 | 
					        "src/ERC20Proxy.sol",
 | 
				
			||||||
        "src/ERC721Proxy.sol",
 | 
					        "src/ERC721Proxy.sol",
 | 
				
			||||||
        "src/MixinAuthorizable.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"
 | 
					        "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "config": {
 | 
					    "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."
 | 
					        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "repository": {
 | 
					    "repository": {
 | 
				
			||||||
@@ -70,6 +70,7 @@
 | 
				
			|||||||
        "@0x/base-contract": "^5.0.2",
 | 
					        "@0x/base-contract": "^5.0.2",
 | 
				
			||||||
        "@0x/contracts-erc20": "^1.0.9",
 | 
					        "@0x/contracts-erc20": "^1.0.9",
 | 
				
			||||||
        "@0x/contracts-erc721": "^1.0.9",
 | 
					        "@0x/contracts-erc721": "^1.0.9",
 | 
				
			||||||
 | 
					        "@0x/contracts-erc1155": "^1.0.0",
 | 
				
			||||||
        "@0x/contracts-utils": "2.0.1",
 | 
					        "@0x/contracts-utils": "2.0.1",
 | 
				
			||||||
        "@0x/order-utils": "^7.0.2",
 | 
					        "@0x/order-utils": "^7.0.2",
 | 
				
			||||||
        "@0x/types": "^2.1.1",
 | 
					        "@0x/types": "^2.1.1",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
import { ContractArtifact } from 'ethereum-types';
 | 
					import { ContractArtifact } from 'ethereum-types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import * as ERC1155Proxy from '../generated-artifacts/ERC1155Proxy.json';
 | 
				
			||||||
import * as ERC20Proxy from '../generated-artifacts/ERC20Proxy.json';
 | 
					import * as ERC20Proxy from '../generated-artifacts/ERC20Proxy.json';
 | 
				
			||||||
import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
 | 
					import * as ERC721Proxy from '../generated-artifacts/ERC721Proxy.json';
 | 
				
			||||||
import * as IAssetData from '../generated-artifacts/IAssetData.json';
 | 
					import * as IAssetData from '../generated-artifacts/IAssetData.json';
 | 
				
			||||||
@@ -15,6 +16,7 @@ import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
 | 
				
			|||||||
export const artifacts = {
 | 
					export const artifacts = {
 | 
				
			||||||
    ERC20Proxy: ERC20Proxy as ContractArtifact,
 | 
					    ERC20Proxy: ERC20Proxy as ContractArtifact,
 | 
				
			||||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
					    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
				
			||||||
 | 
					    ERC1155Proxy: ERC1155Proxy as ContractArtifact,
 | 
				
			||||||
    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
					    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
				
			||||||
    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
					    MultiAssetProxy: MultiAssetProxy as ContractArtifact,
 | 
				
			||||||
    IAssetData: IAssetData as ContractArtifact,
 | 
					    IAssetData: IAssetData as ContractArtifact,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
					 * 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/erc20_proxy';
 | 
				
			||||||
export * from '../generated-wrappers/erc721_proxy';
 | 
					export * from '../generated-wrappers/erc721_proxy';
 | 
				
			||||||
export * from '../generated-wrappers/i_asset_data';
 | 
					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 './erc20_wrapper';
 | 
				
			||||||
export * from './erc721_wrapper';
 | 
					export * from './erc721_wrapper';
 | 
				
			||||||
 | 
					export * from './erc1155_proxy_wrapper';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
					    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
				
			||||||
    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
					    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
				
			||||||
    "files": [
 | 
					    "files": [
 | 
				
			||||||
 | 
					        "generated-artifacts/ERC1155Proxy.json",
 | 
				
			||||||
        "generated-artifacts/ERC20Proxy.json",
 | 
					        "generated-artifacts/ERC20Proxy.json",
 | 
				
			||||||
        "generated-artifacts/ERC721Proxy.json",
 | 
					        "generated-artifacts/ERC721Proxy.json",
 | 
				
			||||||
        "generated-artifacts/IAssetData.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",
 | 
					        "version": "3.0.9",
 | 
				
			||||||
        "changes": [
 | 
					        "changes": [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,11 +38,16 @@ export const constants = {
 | 
				
			|||||||
    NUM_DUMMY_ERC20_TO_DEPLOY: 3,
 | 
					    NUM_DUMMY_ERC20_TO_DEPLOY: 3,
 | 
				
			||||||
    NUM_DUMMY_ERC721_TO_DEPLOY: 2,
 | 
					    NUM_DUMMY_ERC721_TO_DEPLOY: 2,
 | 
				
			||||||
    NUM_ERC721_TOKENS_TO_MINT: 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',
 | 
					    NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
 | 
				
			||||||
    UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
 | 
					    UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
 | 
				
			||||||
    TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)),
 | 
					    TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)),
 | 
				
			||||||
    INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
 | 
					    INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
 | 
				
			||||||
    INITIAL_ERC20_ALLOWANCE: 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: {
 | 
					    STATIC_ORDER_PARAMS: {
 | 
				
			||||||
        makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
 | 
					        makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
 | 
				
			||||||
        takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
 | 
					        takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,9 @@ export {
 | 
				
			|||||||
    MarketBuyOrders,
 | 
					    MarketBuyOrders,
 | 
				
			||||||
    MarketSellOrders,
 | 
					    MarketSellOrders,
 | 
				
			||||||
    ERC721TokenIdsByOwner,
 | 
					    ERC721TokenIdsByOwner,
 | 
				
			||||||
 | 
					    ERC1155FungibleHoldingsByOwner,
 | 
				
			||||||
 | 
					    ERC1155NonFungibleHoldingsByOwner,
 | 
				
			||||||
 | 
					    ERC1155HoldingsByOwner,
 | 
				
			||||||
    OrderStatus,
 | 
					    OrderStatus,
 | 
				
			||||||
    AllowanceAmountScenario,
 | 
					    AllowanceAmountScenario,
 | 
				
			||||||
    AssetDataScenario,
 | 
					    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 {
 | 
					export interface SubmissionContractEventArgs {
 | 
				
			||||||
    transactionId: BigNumber;
 | 
					    transactionId: BigNumber;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,6 +91,8 @@ export {
 | 
				
			|||||||
    SingleAssetData,
 | 
					    SingleAssetData,
 | 
				
			||||||
    ERC20AssetData,
 | 
					    ERC20AssetData,
 | 
				
			||||||
    ERC721AssetData,
 | 
					    ERC721AssetData,
 | 
				
			||||||
 | 
					    ERC1155AssetData,
 | 
				
			||||||
 | 
					    ERC1155AssetDataAbi,
 | 
				
			||||||
    MultiAssetData,
 | 
					    MultiAssetData,
 | 
				
			||||||
    MultiAssetDataWithRecursiveDecoding,
 | 
					    MultiAssetDataWithRecursiveDecoding,
 | 
				
			||||||
    SignatureType,
 | 
					    SignatureType,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,6 +64,7 @@ export {
 | 
				
			|||||||
    AssetData,
 | 
					    AssetData,
 | 
				
			||||||
    ERC20AssetData,
 | 
					    ERC20AssetData,
 | 
				
			||||||
    ERC721AssetData,
 | 
					    ERC721AssetData,
 | 
				
			||||||
 | 
					    ERC1155AssetData,
 | 
				
			||||||
    SingleAssetData,
 | 
					    SingleAssetData,
 | 
				
			||||||
    MultiAssetData,
 | 
					    MultiAssetData,
 | 
				
			||||||
    MultiAssetDataWithRecursiveDecoding,
 | 
					    MultiAssetDataWithRecursiveDecoding,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,10 @@
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                "note": "Add Coordinator EIP712 constants",
 | 
					                "note": "Add Coordinator EIP712 constants",
 | 
				
			||||||
                "pr": 1705
 | 
					                "pr": 1705
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "note": "Added encoding/decoding fdor ERC1155 asset data",
 | 
				
			||||||
 | 
					                "pr": 1661
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,8 @@
 | 
				
			|||||||
import {
 | 
					import {
 | 
				
			||||||
    AssetProxyId,
 | 
					    AssetProxyId,
 | 
				
			||||||
 | 
					    ERC1155AssetData,
 | 
				
			||||||
 | 
					    ERC1155AssetDataAbi,
 | 
				
			||||||
 | 
					    ERC1155AssetDataNoProxyId,
 | 
				
			||||||
    ERC20AssetData,
 | 
					    ERC20AssetData,
 | 
				
			||||||
    ERC721AssetData,
 | 
					    ERC721AssetData,
 | 
				
			||||||
    MultiAssetData,
 | 
					    MultiAssetData,
 | 
				
			||||||
@@ -73,6 +76,47 @@ export const assetDataUtils = {
 | 
				
			|||||||
            tokenId: (decodedAssetData as any).tokenId,
 | 
					            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
 | 
					     * Encodes assetData for multiple AssetProxies into a single hex encoded assetData string, usable in the makerAssetData or
 | 
				
			||||||
     * takerAssetData fields in a 0x order.
 | 
					     * takerAssetData fields in a 0x order.
 | 
				
			||||||
@@ -174,6 +218,7 @@ export const assetDataUtils = {
 | 
				
			|||||||
        if (
 | 
					        if (
 | 
				
			||||||
            assetProxyId !== AssetProxyId.ERC20 &&
 | 
					            assetProxyId !== AssetProxyId.ERC20 &&
 | 
				
			||||||
            assetProxyId !== AssetProxyId.ERC721 &&
 | 
					            assetProxyId !== AssetProxyId.ERC721 &&
 | 
				
			||||||
 | 
					            assetProxyId !== AssetProxyId.ERC1155 &&
 | 
				
			||||||
            assetProxyId !== AssetProxyId.MultiAsset
 | 
					            assetProxyId !== AssetProxyId.MultiAsset
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
            throw new Error(`Invalid assetProxyId: ${assetProxyId}`);
 | 
					            throw new Error(`Invalid assetProxyId: ${assetProxyId}`);
 | 
				
			||||||
@@ -194,6 +239,13 @@ export const assetDataUtils = {
 | 
				
			|||||||
    isERC721AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC721AssetData {
 | 
					    isERC721AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is ERC721AssetData {
 | 
				
			||||||
        return decodedAssetData.assetProxyId === AssetProxyId.ERC721;
 | 
					        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
 | 
					     * Checks if the decoded asset data is valid MultiAsset data
 | 
				
			||||||
     * @param decodedAssetData The decoded asset data to check
 | 
					     * @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.
 | 
					     * Throws if the length or assetProxyId are invalid for the MultiAssetProxy.
 | 
				
			||||||
     * @param assetData Hex encoded assetData string
 | 
					     * @param assetData Hex encoded assetData string
 | 
				
			||||||
@@ -277,6 +337,9 @@ export const assetDataUtils = {
 | 
				
			|||||||
            case AssetProxyId.ERC721:
 | 
					            case AssetProxyId.ERC721:
 | 
				
			||||||
                assetDataUtils.assertIsERC721AssetData(assetData);
 | 
					                assetDataUtils.assertIsERC721AssetData(assetData);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					            case AssetProxyId.ERC1155:
 | 
				
			||||||
 | 
					                assetDataUtils.assertIsERC1155AssetData(assetData);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
            case AssetProxyId.MultiAsset:
 | 
					            case AssetProxyId.MultiAsset:
 | 
				
			||||||
                assetDataUtils.assertIsMultiAssetData(assetData);
 | 
					                assetDataUtils.assertIsMultiAssetData(assetData);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
@@ -287,7 +350,7 @@ export const assetDataUtils = {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Decode any assetData into it's corresponding assetData object
 | 
					     * Decode any assetData into it's corresponding assetData object
 | 
				
			||||||
     * @param assetData Hex encoded assetData string to decode
 | 
					     * @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 {
 | 
					    decodeAssetDataOrThrow(assetData: string): SingleAssetData | MultiAssetData {
 | 
				
			||||||
        const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
 | 
					        const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
 | 
				
			||||||
@@ -298,6 +361,9 @@ export const assetDataUtils = {
 | 
				
			|||||||
            case AssetProxyId.ERC721:
 | 
					            case AssetProxyId.ERC721:
 | 
				
			||||||
                const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData);
 | 
					                const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData);
 | 
				
			||||||
                return erc721AssetData;
 | 
					                return erc721AssetData;
 | 
				
			||||||
 | 
					            case AssetProxyId.ERC1155:
 | 
				
			||||||
 | 
					                const erc1155AssetData = assetDataUtils.decodeERC1155AssetData(assetData);
 | 
				
			||||||
 | 
					                return erc1155AssetData;
 | 
				
			||||||
            case AssetProxyId.MultiAsset:
 | 
					            case AssetProxyId.MultiAsset:
 | 
				
			||||||
                const multiAssetData = assetDataUtils.decodeMultiAssetData(assetData);
 | 
					                const multiAssetData = assetDataUtils.decodeMultiAssetData(assetData);
 | 
				
			||||||
                return multiAssetData;
 | 
					                return multiAssetData;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,8 @@ export {
 | 
				
			|||||||
    SingleAssetData,
 | 
					    SingleAssetData,
 | 
				
			||||||
    ERC20AssetData,
 | 
					    ERC20AssetData,
 | 
				
			||||||
    ERC721AssetData,
 | 
					    ERC721AssetData,
 | 
				
			||||||
 | 
					    ERC1155AssetData,
 | 
				
			||||||
 | 
					    ERC1155AssetDataAbi,
 | 
				
			||||||
    MultiAssetData,
 | 
					    MultiAssetData,
 | 
				
			||||||
    MultiAssetDataWithRecursiveDecoding,
 | 
					    MultiAssetDataWithRecursiveDecoding,
 | 
				
			||||||
    AssetProxyId,
 | 
					    AssetProxyId,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,15 @@ const KNOWN_ERC721_ENCODING = {
 | 
				
			|||||||
    assetData:
 | 
					    assetData:
 | 
				
			||||||
        '0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
 | 
					        '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 = {
 | 
					const KNOWN_MULTI_ASSET_ENCODING = {
 | 
				
			||||||
    amounts: [new BigNumber(1), new BigNumber(1)],
 | 
					    amounts: [new BigNumber(1), new BigNumber(1)],
 | 
				
			||||||
    nestedAssetData: [KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC721_ENCODING.assetData],
 | 
					    nestedAssetData: [KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC721_ENCODING.assetData],
 | 
				
			||||||
@@ -50,6 +59,23 @@ describe('assetDataUtils', () => {
 | 
				
			|||||||
        expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.ERC721);
 | 
					        expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.ERC721);
 | 
				
			||||||
        expect(decodedAssetData.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId);
 | 
					        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', () => {
 | 
					    it('should encode ERC20 and ERC721 multiAssetData', () => {
 | 
				
			||||||
        const assetData = assetDataUtils.encodeMultiAssetData(
 | 
					        const assetData = assetDataUtils.encodeMultiAssetData(
 | 
				
			||||||
            KNOWN_MULTI_ASSET_ENCODING.amounts,
 | 
					            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",
 | 
					        "version": "2.2.1",
 | 
				
			||||||
        "changes": [
 | 
					        "changes": [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -163,6 +163,7 @@ export enum AssetProxyId {
 | 
				
			|||||||
    ERC20 = '0xf47261b0',
 | 
					    ERC20 = '0xf47261b0',
 | 
				
			||||||
    ERC721 = '0x02571792',
 | 
					    ERC721 = '0x02571792',
 | 
				
			||||||
    MultiAsset = '0x94cfcdd7',
 | 
					    MultiAsset = '0x94cfcdd7',
 | 
				
			||||||
 | 
					    ERC1155 = '0x9645780d',
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ERC20AssetData {
 | 
					export interface ERC20AssetData {
 | 
				
			||||||
@@ -176,7 +177,29 @@ export interface ERC721AssetData {
 | 
				
			|||||||
    tokenId: BigNumber;
 | 
					    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 {
 | 
					export interface MultiAssetData {
 | 
				
			||||||
    assetProxyId: string;
 | 
					    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"
 | 
					  resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nan@^2.11.0:
 | 
					nan@^2.11.0:
 | 
				
			||||||
  version "2.13.1"
 | 
					  version "2.12.1"
 | 
				
			||||||
  resolved "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz#a15bee3790bde247e8f38f1d446edcdaeb05f2dd"
 | 
					  resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
 | 
				
			||||||
  integrity sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
nano-json-stream-parser@^0.1.2:
 | 
					nano-json-stream-parser@^0.1.2:
 | 
				
			||||||
  version "0.1.2"
 | 
					  version "0.1.2"
 | 
				
			||||||
@@ -13564,6 +13563,8 @@ react-highlight@0xproject/react-highlight#react-peer-deps:
 | 
				
			|||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    highlight.js "^9.11.0"
 | 
					    highlight.js "^9.11.0"
 | 
				
			||||||
    highlightjs-solidity "^1.0.5"
 | 
					    highlightjs-solidity "^1.0.5"
 | 
				
			||||||
 | 
					    react "^16.4.2"
 | 
				
			||||||
 | 
					    react-dom "^16.4.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
react-hot-loader@^4.3.3:
 | 
					react-hot-loader@^4.3.3:
 | 
				
			||||||
  version "4.3.4"
 | 
					  version "4.3.4"
 | 
				
			||||||
@@ -17653,8 +17654,7 @@ websocket@1.0.26:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
websocket@^1.0.26:
 | 
					websocket@^1.0.26:
 | 
				
			||||||
  version "1.0.28"
 | 
					  version "1.0.28"
 | 
				
			||||||
  resolved "https://registry.npmjs.org/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3"
 | 
					  resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3"
 | 
				
			||||||
  integrity sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA==
 | 
					 | 
				
			||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    debug "^2.2.0"
 | 
					    debug "^2.2.0"
 | 
				
			||||||
    nan "^2.11.0"
 | 
					    nan "^2.11.0"
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user