Split ERC1155 Asset Proxy from ERC1155 POC implementation - squashed
This commit is contained in:
		@@ -1,4 +1,15 @@
 | 
				
			|||||||
[
 | 
					[
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        "name": "ERC1155Proxy",
 | 
				
			||||||
 | 
					        "version": "1.0.0",
 | 
				
			||||||
 | 
					        "changes": [
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "note": "Add ERC1155Proxy implementation",
 | 
				
			||||||
 | 
					                "pr": 0,
 | 
				
			||||||
 | 
					                "networks": {
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        "name": "MultiAssetProxy",
 | 
					        "name": "MultiAssetProxy",
 | 
				
			||||||
        "version": "1.0.0",
 | 
					        "version": "1.0.0",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										257
									
								
								contracts/asset-proxy/contracts/src/ERC1155Proxy.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								contracts/asset-proxy/contracts/src/ERC1155Proxy.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,257 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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 tokenIds (*)         |
 | 
				
			||||||
 | 
					        // |          | 68          |         |   3. offset to tokenValues (*)      |
 | 
				
			||||||
 | 
					        // |          | 100         |         |   4. offset to callbackData (*)     |
 | 
				
			||||||
 | 
					        // | Data     |             |         | tokenIds:                           |
 | 
				
			||||||
 | 
					        // |          | 132         | 32      |   1. tokenIds Length                |
 | 
				
			||||||
 | 
					        // |          | 164         | a       |   2. tokenIds Contents              | 
 | 
				
			||||||
 | 
					        // |          |             |         | tokenValues:                        |
 | 
				
			||||||
 | 
					        // |          | 164 + a     | 32      |   1. tokenValues Length             |
 | 
				
			||||||
 | 
					        // |          | 196 + a     | b       |   2. tokenValues Contents           |
 | 
				
			||||||
 | 
					        // |          |             |         | callbackData                        |
 | 
				
			||||||
 | 
					        // |          | 196 + a + b | 32      |   1. callbackData Length            |
 | 
				
			||||||
 | 
					        // |          | 228 + a + b | c       |   2. callbackData 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 tokenIds (*)         |
 | 
				
			||||||
 | 
					        // |          | 100         |         |   4. offset to tokenValues (*)      |
 | 
				
			||||||
 | 
					        // |          | 132         |         |   5. offset to callbackData (*)     |
 | 
				
			||||||
 | 
					        // | Data     |             |         | tokenIds:                           |
 | 
				
			||||||
 | 
					        // |          | 164         | 32      |   1. tokenIds Length                |
 | 
				
			||||||
 | 
					        // |          | 196         | a       |   2. tokenIds Contents              | 
 | 
				
			||||||
 | 
					        // |          |             |         | tokenValues:                        |
 | 
				
			||||||
 | 
					        // |          | 196 + a     | 32      |   1. tokenValues Length             |
 | 
				
			||||||
 | 
					        // |          | 228 + a     | b       |   2. tokenValues Contents           |
 | 
				
			||||||
 | 
					        // |          |             |         | callbackData                        |
 | 
				
			||||||
 | 
					        // |          | 228 + a + b | 32      |   1. callbackData Length            |
 | 
				
			||||||
 | 
					        // |          | 260 + a + b | c       |   2. callbackData 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 `tokenValues` (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 tokenIds (*)`
 | 
				
			||||||
 | 
					                // 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 `tokenIds`, `tokenValues`, and `callbackData`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // 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, add(36, assetDataOffset), assetDataLength)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Increment by 32 the offsets to `tokenIds`, `tokenValues`, and `callbackData` 
 | 
				
			||||||
 | 
					                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 scaleAmount := calldataload(100)
 | 
				
			||||||
 | 
					                let tokenValuesOffset := add(mload(100), 4) // add 4 for calldata offset
 | 
				
			||||||
 | 
					                let tokenValuesLengthInBytes := mul(
 | 
				
			||||||
 | 
					                    mload(tokenValuesOffset),
 | 
				
			||||||
 | 
					                    32
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                let tokenValuesBegin := add(tokenValuesOffset, 32)
 | 
				
			||||||
 | 
					                let tokenValuesEnd := add(tokenValuesBegin, add(tokenValuesLengthInBytes, 32))
 | 
				
			||||||
 | 
					                for { let tokenValueOffset := tokenValuesBegin }
 | 
				
			||||||
 | 
					                    lt(tokenValueOffset, tokenValuesEnd)
 | 
				
			||||||
 | 
					                    { tokenValueOffset := add(tokenValueOffset, 32) }
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // Load token value and revert if multiplication would result in an overflow
 | 
				
			||||||
 | 
					                    let tokenValue := mload(tokenValueOffset)
 | 
				
			||||||
 | 
					                    let scaledTokenValue := mul(tokenValue, scaleAmount)
 | 
				
			||||||
 | 
					                    let expectedTokenValue := div(scaledTokenValue, scaleAmount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // check for multiplication overflow
 | 
				
			||||||
 | 
					                    if iszero(eq(expectedTokenValue, 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, 36, 64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ////////// 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/@(ERC20Proxy|ERC721Proxy|ERC1155Proxy|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": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,9 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
import { ContractArtifact } from 'ethereum-types';
 | 
					import { ContractArtifact } from 'ethereum-types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import * as DummyERC1155Receiver from '../generated-artifacts/DummyERC1155Receiver.json';
 | 
				
			||||||
 | 
					import * as ERC1155Mintable from '../generated-artifacts/ERC1155Mintable.json';
 | 
				
			||||||
 | 
					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';
 | 
				
			||||||
@@ -13,6 +16,9 @@ import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
 | 
				
			|||||||
import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
 | 
					import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json';
 | 
				
			||||||
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
 | 
					import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
 | 
				
			||||||
export const artifacts = {
 | 
					export const artifacts = {
 | 
				
			||||||
 | 
					    DummyERC1155Receiver: DummyERC1155Receiver as ContractArtifact,
 | 
				
			||||||
 | 
					    ERC1155Mintable: ERC1155Mintable as ContractArtifact,
 | 
				
			||||||
 | 
					    ERC1155Proxy: ERC1155Proxy as ContractArtifact,
 | 
				
			||||||
    ERC20Proxy: ERC20Proxy as ContractArtifact,
 | 
					    ERC20Proxy: ERC20Proxy as ContractArtifact,
 | 
				
			||||||
    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
					    ERC721Proxy: ERC721Proxy as ContractArtifact,
 | 
				
			||||||
    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
					    MixinAuthorizable: MixinAuthorizable as ContractArtifact,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,9 @@
 | 
				
			|||||||
 * 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/dummy_erc1155_receiver';
 | 
				
			||||||
 | 
					export * from '../generated-wrappers/erc1155_mintable';
 | 
				
			||||||
 | 
					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';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,10 +34,16 @@ import {
 | 
				
			|||||||
    ERC20Wrapper,
 | 
					    ERC20Wrapper,
 | 
				
			||||||
    ERC721ProxyContract,
 | 
					    ERC721ProxyContract,
 | 
				
			||||||
    ERC721Wrapper,
 | 
					    ERC721Wrapper,
 | 
				
			||||||
 | 
					    ERC1155Wrapper,
 | 
				
			||||||
 | 
					    ERC1155ProxyContract,
 | 
				
			||||||
    IAssetDataContract,
 | 
					    IAssetDataContract,
 | 
				
			||||||
    IAssetProxyContract,
 | 
					    IAssetProxyContract,
 | 
				
			||||||
    MultiAssetProxyContract,
 | 
					    MultiAssetProxyContract,
 | 
				
			||||||
 | 
					    ERC1155MintableContract,
 | 
				
			||||||
 | 
					    DummyERC1155ReceiverContract,
 | 
				
			||||||
 | 
					    DummyERC1155ReceiverBatchTokenReceivedEventArgs,
 | 
				
			||||||
} from '../src';
 | 
					} from '../src';
 | 
				
			||||||
 | 
					import values from 'ramda/es/values';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
chaiSetup.configure();
 | 
					chaiSetup.configure();
 | 
				
			||||||
const expect = chai.expect;
 | 
					const expect = chai.expect;
 | 
				
			||||||
@@ -68,15 +74,22 @@ describe('Asset Transfer Proxies', () => {
 | 
				
			|||||||
    let erc721Receiver: DummyERC721ReceiverContract;
 | 
					    let erc721Receiver: DummyERC721ReceiverContract;
 | 
				
			||||||
    let erc20Proxy: ERC20ProxyContract;
 | 
					    let erc20Proxy: ERC20ProxyContract;
 | 
				
			||||||
    let erc721Proxy: ERC721ProxyContract;
 | 
					    let erc721Proxy: ERC721ProxyContract;
 | 
				
			||||||
 | 
					    let erc1155Proxy: ERC721ProxyContract;
 | 
				
			||||||
 | 
					    let erc1155Receiver: DummyERC1155ReceiverContract;
 | 
				
			||||||
    let noReturnErc20Token: DummyNoReturnERC20TokenContract;
 | 
					    let noReturnErc20Token: DummyNoReturnERC20TokenContract;
 | 
				
			||||||
    let multipleReturnErc20Token: DummyMultipleReturnERC20TokenContract;
 | 
					    let multipleReturnErc20Token: DummyMultipleReturnERC20TokenContract;
 | 
				
			||||||
    let multiAssetProxy: MultiAssetProxyContract;
 | 
					    let multiAssetProxy: MultiAssetProxyContract;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let erc20Wrapper: ERC20Wrapper;
 | 
					    let erc20Wrapper: ERC20Wrapper;
 | 
				
			||||||
    let erc721Wrapper: ERC721Wrapper;
 | 
					    let erc721Wrapper: ERC721Wrapper;
 | 
				
			||||||
 | 
					    let erc1155Wrapper: ERC1155Wrapper;
 | 
				
			||||||
    let erc721AFromTokenId: BigNumber;
 | 
					    let erc721AFromTokenId: BigNumber;
 | 
				
			||||||
    let erc721BFromTokenId: BigNumber;
 | 
					    let erc721BFromTokenId: BigNumber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let erc1155Token: ERC1155MintableContract;
 | 
				
			||||||
 | 
					    let erc1155FungibleTokenIds: BigNumber[];
 | 
				
			||||||
 | 
					    let erc1155NonFungibleTokenIds: BigNumber[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    before(async () => {
 | 
					    before(async () => {
 | 
				
			||||||
        await blockchainLifecycle.startAsync();
 | 
					        await blockchainLifecycle.startAsync();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -89,10 +102,12 @@ describe('Asset Transfer Proxies', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
 | 
					        erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
 | 
				
			||||||
        erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
 | 
					        erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
 | 
				
			||||||
 | 
					        erc1155Wrapper = new ERC1155Wrapper(provider, usedAddresses, owner);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Deploy AssetProxies
 | 
					        // Deploy AssetProxies
 | 
				
			||||||
        erc20Proxy = await erc20Wrapper.deployProxyAsync();
 | 
					        erc20Proxy = await erc20Wrapper.deployProxyAsync();
 | 
				
			||||||
        erc721Proxy = await erc721Wrapper.deployProxyAsync();
 | 
					        erc721Proxy = await erc721Wrapper.deployProxyAsync();
 | 
				
			||||||
 | 
					        erc1155Proxy = await erc1155Wrapper.deployProxyAsync();
 | 
				
			||||||
        multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
 | 
					        multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
 | 
				
			||||||
            artifacts.MultiAssetProxy,
 | 
					            artifacts.MultiAssetProxy,
 | 
				
			||||||
            provider,
 | 
					            provider,
 | 
				
			||||||
@@ -127,6 +142,20 @@ describe('Asset Transfer Proxies', () => {
 | 
				
			|||||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
					            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Configure ERC1155Proxy
 | 
				
			||||||
 | 
					        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					            await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
 | 
				
			||||||
 | 
					                from: owner,
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					            await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
 | 
				
			||||||
 | 
					                from: owner,
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Configure MultiAssetProxy
 | 
					        // Configure MultiAssetProxy
 | 
				
			||||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
					        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
            await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
 | 
					            await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
 | 
				
			||||||
@@ -208,11 +237,21 @@ describe('Asset Transfer Proxies', () => {
 | 
				
			|||||||
            provider,
 | 
					            provider,
 | 
				
			||||||
            txDefaults,
 | 
					            txDefaults,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					 | 
				
			||||||
        await erc721Wrapper.setBalancesAndAllowancesAsync();
 | 
					        await erc721Wrapper.setBalancesAndAllowancesAsync();
 | 
				
			||||||
        const erc721Balances = await erc721Wrapper.getBalancesAsync();
 | 
					        const erc721Balances = await erc721Wrapper.getBalancesAsync();
 | 
				
			||||||
        erc721AFromTokenId = erc721Balances[fromAddress][erc721TokenA.address][0];
 | 
					        erc721AFromTokenId = erc721Balances[fromAddress][erc721TokenA.address][0];
 | 
				
			||||||
        erc721BFromTokenId = erc721Balances[fromAddress][erc721TokenB.address][0];
 | 
					        erc721BFromTokenId = erc721Balances[fromAddress][erc721TokenB.address][0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Deploy and configure ERC1155 tokens and receiver
 | 
				
			||||||
 | 
					        [erc1155Token] = await erc1155Wrapper.deployDummyTokensAsync();
 | 
				
			||||||
 | 
					        erc1155Receiver = await DummyERC1155ReceiverContract.deployFrom0xArtifactAsync(
 | 
				
			||||||
 | 
					            artifacts.DummyERC1155Receiver,
 | 
				
			||||||
 | 
					            provider,
 | 
				
			||||||
 | 
					            txDefaults,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        await erc1155Wrapper.setBalancesAndAllowancesAsync();
 | 
				
			||||||
 | 
					        erc1155FungibleTokenIds = erc1155Wrapper.getFungibleTokenIds();
 | 
				
			||||||
 | 
					        erc1155NonFungibleTokenIds = erc1155Wrapper.getNonFungibleTokenIds();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    beforeEach(async () => {
 | 
					    beforeEach(async () => {
 | 
				
			||||||
        await blockchainLifecycle.startAsync();
 | 
					        await blockchainLifecycle.startAsync();
 | 
				
			||||||
@@ -477,7 +516,6 @@ describe('Asset Transfer Proxies', () => {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					 | 
				
			||||||
    describe('ERC721Proxy', () => {
 | 
					    describe('ERC721Proxy', () => {
 | 
				
			||||||
        it('should revert if undefined function is called', async () => {
 | 
					        it('should revert if undefined function is called', async () => {
 | 
				
			||||||
            const undefinedSelector = '0x01020304';
 | 
					            const undefinedSelector = '0x01020304';
 | 
				
			||||||
@@ -1286,6 +1324,373 @@ describe('Asset Transfer Proxies', () => {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    describe.only('ERC1155Proxy', () => {
 | 
				
			||||||
 | 
					        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 token', async () => {
 | 
				
			||||||
 | 
					                // Construct ERC1155 asset data
 | 
				
			||||||
 | 
					                const callbackData = "0x";
 | 
				
			||||||
 | 
					                const fungibleTokenIdToTransfer = erc1155FungibleTokenIds[0];
 | 
				
			||||||
 | 
					                const tokenIdsToTransfer = [fungibleTokenIdToTransfer];
 | 
				
			||||||
 | 
					                const tokenValuesToTransfer = [new BigNumber(10)];
 | 
				
			||||||
 | 
					                const encodedAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Token.address, tokenIdsToTransfer, tokenValuesToTransfer, callbackData);
 | 
				
			||||||
 | 
					                // Verify pre-condition
 | 
				
			||||||
 | 
					                const initialHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const initialSenderBalance = initialHoldingsByOwner.fungible[fromAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const initialReceiverBalance = initialHoldingsByOwner.fungible[toAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                // Perform a transfer from fromAddress to toAddress
 | 
				
			||||||
 | 
					                const perUnitValue = new BigNumber(1000);
 | 
				
			||||||
 | 
					                const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
				
			||||||
 | 
					                    encodedAssetData,
 | 
				
			||||||
 | 
					                    fromAddress,
 | 
				
			||||||
 | 
					                    toAddress,
 | 
				
			||||||
 | 
					                    perUnitValue,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					                    await web3Wrapper.sendTransactionAsync({
 | 
				
			||||||
 | 
					                        to: erc1155Proxy.address,
 | 
				
			||||||
 | 
					                        data,
 | 
				
			||||||
 | 
					                        from: authorized,
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // Verify transfer was successful
 | 
				
			||||||
 | 
					                const totalValueTransferred = tokenValuesToTransfer[0].times(perUnitValue);
 | 
				
			||||||
 | 
					                const newHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const newSenderBalance = newHoldingsByOwner.fungible[fromAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const expectedNewSenderBalance = initialSenderBalance.minus(totalValueTransferred);
 | 
				
			||||||
 | 
					                const newReceiverBalance = newHoldingsByOwner.fungible[toAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const expectedNewReceiverBalance = initialReceiverBalance.plus(totalValueTransferred);
 | 
				
			||||||
 | 
					                expect(newSenderBalance).to.be.bignumber.equal(expectedNewSenderBalance);
 | 
				
			||||||
 | 
					                expect(newReceiverBalance).to.be.bignumber.equal(expectedNewReceiverBalance);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should successfully transfer value for a collection of fungible tokens of the same id', async () => {
 | 
				
			||||||
 | 
					                // Construct ERC1155 asset data
 | 
				
			||||||
 | 
					                const callbackData = "0x";
 | 
				
			||||||
 | 
					                const fungibleTokenIdToTransfer = erc1155FungibleTokenIds[0];
 | 
				
			||||||
 | 
					                const tokenIdsToTransfer = [fungibleTokenIdToTransfer, fungibleTokenIdToTransfer, fungibleTokenIdToTransfer];
 | 
				
			||||||
 | 
					                const tokenValuesToTransfer = [new BigNumber(10), new BigNumber(20), new BigNumber(30)];
 | 
				
			||||||
 | 
					                const encodedAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Token.address, tokenIdsToTransfer, tokenValuesToTransfer, callbackData);
 | 
				
			||||||
 | 
					                // Verify pre-condition
 | 
				
			||||||
 | 
					                const initialHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const initialSenderBalance = initialHoldingsByOwner.fungible[fromAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const initialReceiverBalance = initialHoldingsByOwner.fungible[toAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                // Perform a transfer from fromAddress to toAddress
 | 
				
			||||||
 | 
					                const perUnitValue = new BigNumber(1000);
 | 
				
			||||||
 | 
					                const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
				
			||||||
 | 
					                    encodedAssetData,
 | 
				
			||||||
 | 
					                    fromAddress,
 | 
				
			||||||
 | 
					                    toAddress,
 | 
				
			||||||
 | 
					                    perUnitValue,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					                    await web3Wrapper.sendTransactionAsync({
 | 
				
			||||||
 | 
					                        to: erc1155Proxy.address,
 | 
				
			||||||
 | 
					                        data,
 | 
				
			||||||
 | 
					                        from: authorized,
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // Verify transfer was successful
 | 
				
			||||||
 | 
					                const totalValueTransferred = _.reduce(tokenValuesToTransfer, (sum: BigNumber, value: BigNumber) => {return sum.plus(value)}, new BigNumber(0)).times(perUnitValue);
 | 
				
			||||||
 | 
					                const newHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const newSenderBalance = newHoldingsByOwner.fungible[fromAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const expectedNewSenderBalance = initialSenderBalance.minus(totalValueTransferred);
 | 
				
			||||||
 | 
					                const newReceiverBalance = newHoldingsByOwner.fungible[toAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const expectedNewReceiverBalance = initialReceiverBalance.plus(totalValueTransferred);
 | 
				
			||||||
 | 
					                expect(newSenderBalance).to.be.bignumber.equal(expectedNewSenderBalance);
 | 
				
			||||||
 | 
					                expect(newReceiverBalance).to.be.bignumber.equal(expectedNewReceiverBalance);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should successfully transfer value for a collection of fungible tokens of different ids', async () => {
 | 
				
			||||||
 | 
					                // Construct ERC1155 asset data
 | 
				
			||||||
 | 
					                const callbackData = "0x";
 | 
				
			||||||
 | 
					                const tokenIdsToTransfer = erc1155FungibleTokenIds.slice(0, 2);
 | 
				
			||||||
 | 
					                const tokenValuesToTransfer = [new BigNumber(10), new BigNumber(20)];
 | 
				
			||||||
 | 
					                const encodedAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Token.address, tokenIdsToTransfer, tokenValuesToTransfer, callbackData);
 | 
				
			||||||
 | 
					                // Verify pre-condition
 | 
				
			||||||
 | 
					                const initialHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const initialSenderBalances: BigNumber[] = [];
 | 
				
			||||||
 | 
					                const initialReceiverBalances: BigNumber[] = [];
 | 
				
			||||||
 | 
					                _.each(tokenIdsToTransfer, (tokenIdToTransfer: BigNumber) => {
 | 
				
			||||||
 | 
					                    initialSenderBalances.push(initialHoldingsByOwner.fungible[fromAddress][erc1155Token.address][tokenIdToTransfer.toString()]);
 | 
				
			||||||
 | 
					                    initialReceiverBalances.push(initialHoldingsByOwner.fungible[toAddress][erc1155Token.address][tokenIdToTransfer.toString()]);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					                // Perform a transfer from fromAddress to toAddress
 | 
				
			||||||
 | 
					                const perUnitValue = new BigNumber(1000);
 | 
				
			||||||
 | 
					                const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
				
			||||||
 | 
					                    encodedAssetData,
 | 
				
			||||||
 | 
					                    fromAddress,
 | 
				
			||||||
 | 
					                    toAddress,
 | 
				
			||||||
 | 
					                    perUnitValue,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					                    await web3Wrapper.sendTransactionAsync({
 | 
				
			||||||
 | 
					                        to: erc1155Proxy.address,
 | 
				
			||||||
 | 
					                        data,
 | 
				
			||||||
 | 
					                        from: authorized,
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // Verify transfer was successful
 | 
				
			||||||
 | 
					                const newHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                _.each(tokenIdsToTransfer, (tokenIdToTransfer: BigNumber, i: number) => {
 | 
				
			||||||
 | 
					                    const totalValueTransferred = tokenValuesToTransfer[i].times(perUnitValue);
 | 
				
			||||||
 | 
					                    const newSenderBalance = newHoldingsByOwner.fungible[fromAddress][erc1155Token.address][tokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                    const expectedNewSenderBalance = initialSenderBalances[i].minus(totalValueTransferred);
 | 
				
			||||||
 | 
					                    const newReceiverBalance = newHoldingsByOwner.fungible[toAddress][erc1155Token.address][tokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                    const expectedNewReceiverBalance = initialReceiverBalances[i].plus(totalValueTransferred);
 | 
				
			||||||
 | 
					                    expect(newSenderBalance).to.be.bignumber.equal(expectedNewSenderBalance);
 | 
				
			||||||
 | 
					                    expect(newReceiverBalance).to.be.bignumber.equal(expectedNewReceiverBalance);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should successfully transfer a non-fungible token', async () => {
 | 
				
			||||||
 | 
					                // Construct ERC1155 asset data
 | 
				
			||||||
 | 
					                const callbackData = "0x";
 | 
				
			||||||
 | 
					                const nonFungibleTokenIdToTransfer = erc1155NonFungibleTokenIds[0];
 | 
				
			||||||
 | 
					                const initialHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const nftToTransfer = initialHoldingsByOwner.nonFungible[fromAddress][erc1155Token.address][nonFungibleTokenIdToTransfer.toString()][0];
 | 
				
			||||||
 | 
					                const tokenIdsToTransfer = [nftToTransfer];
 | 
				
			||||||
 | 
					                const tokenValuesToTransfer = [new BigNumber(1)];
 | 
				
			||||||
 | 
					                const encodedAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Token.address, tokenIdsToTransfer, tokenValuesToTransfer, callbackData);
 | 
				
			||||||
 | 
					                // Verify precondition
 | 
				
			||||||
 | 
					                const nftHolder = await erc1155Wrapper.ownerOfNonFungibleAsync(erc1155Token.address, nftToTransfer);
 | 
				
			||||||
 | 
					                expect(nftHolder).to.be.equal(fromAddress);
 | 
				
			||||||
 | 
					                // Perform a transfer from fromAddress to toAddress
 | 
				
			||||||
 | 
					                const perUnitValue = new BigNumber(1);
 | 
				
			||||||
 | 
					                const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
				
			||||||
 | 
					                    encodedAssetData,
 | 
				
			||||||
 | 
					                    fromAddress,
 | 
				
			||||||
 | 
					                    toAddress,
 | 
				
			||||||
 | 
					                    perUnitValue,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					                    await web3Wrapper.sendTransactionAsync({
 | 
				
			||||||
 | 
					                        to: erc1155Proxy.address,
 | 
				
			||||||
 | 
					                        data,
 | 
				
			||||||
 | 
					                        from: authorized,
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // Verify transfer was successful
 | 
				
			||||||
 | 
					                const newNftHolder = await erc1155Wrapper.ownerOfNonFungibleAsync(erc1155Token.address, nftToTransfer);
 | 
				
			||||||
 | 
					                expect(newNftHolder).to.be.equal(toAddress);
 | 
				
			||||||
 | 
					                // Verify balances updated successfully
 | 
				
			||||||
 | 
					                const newHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const newNftsForFromAddress = newHoldingsByOwner.nonFungible[fromAddress][erc1155Token.address][nonFungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const newNftsForToAddress = newHoldingsByOwner.nonFungible[toAddress][erc1155Token.address][nonFungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                expect(_.find(newNftsForFromAddress, nftToTransfer)).to.be.undefined();
 | 
				
			||||||
 | 
					                expect(_.find(newNftsForToAddress, nftToTransfer)).to.be.not.undefined();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should successfully transfer value for a combination of fungible/non-fungible tokens', async () => {
 | 
				
			||||||
 | 
					                // Construct ERC1155 asset data
 | 
				
			||||||
 | 
					                const callbackData = "0x";
 | 
				
			||||||
 | 
					                const fungibleTokenIdToTransfer = erc1155FungibleTokenIds[0];
 | 
				
			||||||
 | 
					                const nonFungibleTokenIdToTransfer = erc1155NonFungibleTokenIds[0];
 | 
				
			||||||
 | 
					                const initialHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const nftToTransfer = initialHoldingsByOwner.nonFungible[fromAddress][erc1155Token.address][nonFungibleTokenIdToTransfer.toString()][0];
 | 
				
			||||||
 | 
					                const tokenIdsToTransfer = [fungibleTokenIdToTransfer, nftToTransfer];
 | 
				
			||||||
 | 
					                const tokenValuesToTransfer = [new BigNumber(10), new BigNumber(1)];
 | 
				
			||||||
 | 
					                const encodedAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Token.address, tokenIdsToTransfer, tokenValuesToTransfer, callbackData);
 | 
				
			||||||
 | 
					                // Verify precondition
 | 
				
			||||||
 | 
					                const initialSenderBalance = initialHoldingsByOwner.fungible[fromAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const initialReceiverBalance = initialHoldingsByOwner.fungible[toAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const nftHolder = await erc1155Wrapper.ownerOfNonFungibleAsync(erc1155Token.address, nftToTransfer);
 | 
				
			||||||
 | 
					                expect(nftHolder).to.be.equal(fromAddress);
 | 
				
			||||||
 | 
					                // Perform a transfer from fromAddress to toAddress
 | 
				
			||||||
 | 
					                const perUnitValue = new BigNumber(1);
 | 
				
			||||||
 | 
					                const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
				
			||||||
 | 
					                    encodedAssetData,
 | 
				
			||||||
 | 
					                    fromAddress,
 | 
				
			||||||
 | 
					                    toAddress,
 | 
				
			||||||
 | 
					                    perUnitValue,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					                    await web3Wrapper.sendTransactionAsync({
 | 
				
			||||||
 | 
					                        to: erc1155Proxy.address,
 | 
				
			||||||
 | 
					                        data,
 | 
				
			||||||
 | 
					                        from: authorized,
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // Verify non-fungible transfer was successful
 | 
				
			||||||
 | 
					                const newNftHolder = await erc1155Wrapper.ownerOfNonFungibleAsync(erc1155Token.address, nftToTransfer);
 | 
				
			||||||
 | 
					                expect(newNftHolder).to.be.equal(toAddress);
 | 
				
			||||||
 | 
					                // Verify non-fungible balances updated successfully
 | 
				
			||||||
 | 
					                const newHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const newNftsForFromAddress = newHoldingsByOwner.nonFungible[fromAddress][erc1155Token.address][nonFungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const newNftsForToAddress = newHoldingsByOwner.nonFungible[toAddress][erc1155Token.address][nonFungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                expect(_.find(newNftsForFromAddress, nftToTransfer)).to.be.undefined();
 | 
				
			||||||
 | 
					                expect(_.find(newNftsForToAddress, nftToTransfer)).to.be.not.undefined();
 | 
				
			||||||
 | 
					                // Verify fungible transfer was successful
 | 
				
			||||||
 | 
					                const totalValueTransferred = tokenValuesToTransfer[0].times(perUnitValue);
 | 
				
			||||||
 | 
					                const newSenderBalance = newHoldingsByOwner.fungible[fromAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const expectedNewSenderBalance = initialSenderBalance.minus(totalValueTransferred);
 | 
				
			||||||
 | 
					                const newReceiverBalance = newHoldingsByOwner.fungible[toAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const expectedNewReceiverBalance = initialReceiverBalance.plus(totalValueTransferred);
 | 
				
			||||||
 | 
					                expect(newSenderBalance).to.be.bignumber.equal(expectedNewSenderBalance);
 | 
				
			||||||
 | 
					                expect(newReceiverBalance).to.be.bignumber.equal(expectedNewReceiverBalance);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should successfully transfer value and ignore extra assetData', async () => {
 | 
				
			||||||
 | 
					                // Construct ERC1155 asset data
 | 
				
			||||||
 | 
					                const callbackData = "0x";
 | 
				
			||||||
 | 
					                const fungibleTokenIdToTransfer = erc1155FungibleTokenIds[0];
 | 
				
			||||||
 | 
					                const tokenIdsToTransfer = [fungibleTokenIdToTransfer];
 | 
				
			||||||
 | 
					                const tokenValuesToTransfer = [new BigNumber(10)];
 | 
				
			||||||
 | 
					                const encodedAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Token.address, tokenIdsToTransfer, tokenValuesToTransfer, callbackData);
 | 
				
			||||||
 | 
					                const extraData = '0102030405060708';
 | 
				
			||||||
 | 
					                const encodedAssetDataPlusExtraData = `${encodedAssetData}${extraData}`;
 | 
				
			||||||
 | 
					                // Verify pre-condition
 | 
				
			||||||
 | 
					                const initialHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const initialSenderBalance = initialHoldingsByOwner.fungible[fromAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const initialReceiverBalance = initialHoldingsByOwner.fungible[toAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                // Perform a transfer from fromAddress to toAddress
 | 
				
			||||||
 | 
					                const perUnitValue = new BigNumber(1000);
 | 
				
			||||||
 | 
					                const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
				
			||||||
 | 
					                    encodedAssetDataPlusExtraData,
 | 
				
			||||||
 | 
					                    fromAddress,
 | 
				
			||||||
 | 
					                    toAddress,
 | 
				
			||||||
 | 
					                    perUnitValue,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                await web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					                    await web3Wrapper.sendTransactionAsync({
 | 
				
			||||||
 | 
					                        to: erc1155Proxy.address,
 | 
				
			||||||
 | 
					                        data,
 | 
				
			||||||
 | 
					                        from: authorized,
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // Verify transfer was successful
 | 
				
			||||||
 | 
					                const totalValueTransferred = tokenValuesToTransfer[0].times(perUnitValue);
 | 
				
			||||||
 | 
					                const newHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const newSenderBalance = newHoldingsByOwner.fungible[fromAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const expectedNewSenderBalance = initialSenderBalance.minus(totalValueTransferred);
 | 
				
			||||||
 | 
					                const newReceiverBalance = newHoldingsByOwner.fungible[toAddress][erc1155Token.address][fungibleTokenIdToTransfer.toString()];
 | 
				
			||||||
 | 
					                const expectedNewReceiverBalance = initialReceiverBalance.plus(totalValueTransferred);
 | 
				
			||||||
 | 
					                expect(newSenderBalance).to.be.bignumber.equal(expectedNewSenderBalance);
 | 
				
			||||||
 | 
					                expect(newReceiverBalance).to.be.bignumber.equal(expectedNewReceiverBalance);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it.only('should successfully execute callback when transferring to a smart contract', async () => {
 | 
				
			||||||
 | 
					                // Construct ERC1155 asset data
 | 
				
			||||||
 | 
					                const callbackData = "0x";
 | 
				
			||||||
 | 
					                const nonFungibleTokenIdToTransfer = erc1155NonFungibleTokenIds[0];
 | 
				
			||||||
 | 
					                const initialHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const nftToTransfer = initialHoldingsByOwner.nonFungible[fromAddress][erc1155Token.address][nonFungibleTokenIdToTransfer.toString()][0];
 | 
				
			||||||
 | 
					                const tokenIdsToTransfer = [nftToTransfer];
 | 
				
			||||||
 | 
					                const tokenValuesToTransfer = [new BigNumber(1)];
 | 
				
			||||||
 | 
					                const encodedAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Token.address, tokenIdsToTransfer, tokenValuesToTransfer, callbackData);
 | 
				
			||||||
 | 
					                // Verify precondition
 | 
				
			||||||
 | 
					                const nftHolder = await erc1155Wrapper.ownerOfNonFungibleAsync(erc1155Token.address, nftToTransfer);
 | 
				
			||||||
 | 
					                expect(nftHolder).to.be.equal(fromAddress);
 | 
				
			||||||
 | 
					                // Perform a transfer from fromAddress to toAddress
 | 
				
			||||||
 | 
					                const perUnitValue = new BigNumber(1);
 | 
				
			||||||
 | 
					                const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
				
			||||||
 | 
					                    encodedAssetData,
 | 
				
			||||||
 | 
					                    fromAddress,
 | 
				
			||||||
 | 
					                    erc1155Receiver.address,
 | 
				
			||||||
 | 
					                    perUnitValue,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                const logDecoder = new LogDecoder(web3Wrapper, artifacts);
 | 
				
			||||||
 | 
					                const txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
 | 
				
			||||||
 | 
					                    await web3Wrapper.sendTransactionAsync({
 | 
				
			||||||
 | 
					                        to: erc1155Proxy.address,
 | 
				
			||||||
 | 
					                        data,
 | 
				
			||||||
 | 
					                        from: authorized,
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // Verify logs
 | 
				
			||||||
 | 
					                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(fromAddress);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.tokenIds.length).to.be.deep.equal(1);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokenIdsToTransfer[0]);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.tokenValues.length).to.be.deep.equal(1);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(tokenValuesToTransfer[0]);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.data).to.be.deep.equal(callbackData);
 | 
				
			||||||
 | 
					                // Verify transfer was successful
 | 
				
			||||||
 | 
					                const newNftHolder = await erc1155Wrapper.ownerOfNonFungibleAsync(erc1155Token.address, nftToTransfer);
 | 
				
			||||||
 | 
					                expect(newNftHolder).to.be.equal(erc1155Receiver.address);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it.only('should successfully execute callback when transferring to a smart conract when there is callback data', async () => {
 | 
				
			||||||
 | 
					                // Construct ERC1155 asset data
 | 
				
			||||||
 | 
					                const callbackData = "0x12345678";
 | 
				
			||||||
 | 
					                const nonFungibleTokenIdToTransfer = erc1155NonFungibleTokenIds[0];
 | 
				
			||||||
 | 
					                const initialHoldingsByOwner = await erc1155Wrapper.getBalancesAsync();
 | 
				
			||||||
 | 
					                const nftToTransfer = initialHoldingsByOwner.nonFungible[fromAddress][erc1155Token.address][nonFungibleTokenIdToTransfer.toString()][0];
 | 
				
			||||||
 | 
					                const tokenIdsToTransfer = [nftToTransfer];
 | 
				
			||||||
 | 
					                const tokenValuesToTransfer = [new BigNumber(1)];
 | 
				
			||||||
 | 
					                const encodedAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Token.address, tokenIdsToTransfer, tokenValuesToTransfer, callbackData);
 | 
				
			||||||
 | 
					                // Verify precondition
 | 
				
			||||||
 | 
					                const nftHolder = await erc1155Wrapper.ownerOfNonFungibleAsync(erc1155Token.address, nftToTransfer);
 | 
				
			||||||
 | 
					                expect(nftHolder).to.be.equal(fromAddress);
 | 
				
			||||||
 | 
					                // Perform a transfer from fromAddress to toAddress
 | 
				
			||||||
 | 
					                const perUnitValue = new BigNumber(1);
 | 
				
			||||||
 | 
					                const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
 | 
				
			||||||
 | 
					                    encodedAssetData,
 | 
				
			||||||
 | 
					                    fromAddress,
 | 
				
			||||||
 | 
					                    erc1155Receiver.address,
 | 
				
			||||||
 | 
					                    perUnitValue,
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                const logDecoder = new LogDecoder(web3Wrapper, artifacts);
 | 
				
			||||||
 | 
					                const txReceipt = await logDecoder.getTxWithDecodedLogsAsync(
 | 
				
			||||||
 | 
					                    await web3Wrapper.sendTransactionAsync({
 | 
				
			||||||
 | 
					                        to: erc1155Proxy.address,
 | 
				
			||||||
 | 
					                        data,
 | 
				
			||||||
 | 
					                        from: authorized,
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                // Verify logs
 | 
				
			||||||
 | 
					                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(fromAddress);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.tokenIds.length).to.be.deep.equal(1);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokenIdsToTransfer[0]);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.tokenValues.length).to.be.deep.equal(1);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(tokenValuesToTransfer[0]);
 | 
				
			||||||
 | 
					                expect(receiverLog.args.data).to.be.deep.equal(callbackData);
 | 
				
			||||||
 | 
					                // Verify transfer was successful
 | 
				
			||||||
 | 
					                const newNftHolder = await erc1155Wrapper.ownerOfNonFungibleAsync(erc1155Token.address, nftToTransfer);
 | 
				
			||||||
 | 
					                expect(newNftHolder).to.be.equal(erc1155Receiver.address);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should propagate revert reason from erc1155 contract failure', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if transferring the same non-fungible token more than once', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if tansferring 0 amount of any token', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if there is a multiplication overflow', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if there is a multiplication overflow, when transferring multiple tokens', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if transferring > 1 instances of a non-fungible token (amount field >1)', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if transferring > 1 instances of a non-fungible token (value field >1)', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if sender balance is insufficient', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if sender allowance is insufficient', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            it('should revert if caller is not authorized', async () => {
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
// tslint:enable:no-unnecessary-type-assertion
 | 
					// tslint:enable:no-unnecessary-type-assertion
 | 
				
			||||||
// tslint:disable:max-file-line-count
 | 
					// tslint:disable:max-file-line-count
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										288
									
								
								contracts/asset-proxy/test/utils/erc1155_wrapper.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								contracts/asset-proxy/test/utils/erc1155_wrapper.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,288 @@
 | 
				
			|||||||
 | 
					import { constants, ERC1155HoldingsByOwner, ERC1155FungibleHoldingsByOwner, ERC1155NonFungibleHoldingsByOwner, LogDecoder, txDefaults } from '@0x/contracts-test-utils';
 | 
				
			||||||
 | 
					import { generatePseudoRandomSalt } from '@0x/order-utils';
 | 
				
			||||||
 | 
					import { BigNumber } from '@0x/utils';
 | 
				
			||||||
 | 
					import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
				
			||||||
 | 
					import { Provider } from 'ethereum-types';
 | 
				
			||||||
 | 
					import * as _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { LogWithDecodedArgs } from 'ethereum-types';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { artifacts, ERC1155MintableContract, ERC1155ProxyContract, ERC1155MintableTransferSingleEventArgs } from '../../src';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class ERC1155Wrapper {
 | 
				
			||||||
 | 
					    private readonly _tokenOwnerAddresses: string[];
 | 
				
			||||||
 | 
					    private readonly _fungibleTokenIds: string[];
 | 
				
			||||||
 | 
					    private readonly _nonFungibleTokenIds: string[];
 | 
				
			||||||
 | 
					    private readonly _nfts: {id: BigNumber, tokenId: BigNumber}[];
 | 
				
			||||||
 | 
					    private readonly _contractOwnerAddress: string;
 | 
				
			||||||
 | 
					    private readonly _web3Wrapper: Web3Wrapper;
 | 
				
			||||||
 | 
					    private readonly _provider: Provider;
 | 
				
			||||||
 | 
					    private readonly _logDecoder: LogDecoder;
 | 
				
			||||||
 | 
					    private readonly _dummyTokenContracts: ERC1155MintableContract[];
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
 | 
					        this._logDecoder = new LogDecoder(this._web3Wrapper, artifacts);
 | 
				
			||||||
 | 
					        this._dummyTokenContracts = [];
 | 
				
			||||||
 | 
					        this._tokenOwnerAddresses = tokenOwnerAddresses;
 | 
				
			||||||
 | 
					        this._contractOwnerAddress = contractOwnerAddress;
 | 
				
			||||||
 | 
					        this._fungibleTokenIds = [];
 | 
				
			||||||
 | 
					        this._nonFungibleTokenIds = [];
 | 
				
			||||||
 | 
					        this._nfts = [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async deployDummyTokensAsync(): Promise<ERC1155MintableContract[]> {
 | 
				
			||||||
 | 
					        // tslint:disable-next-line:no-unused-variable
 | 
				
			||||||
 | 
					        for (const i of _.times(constants.NUM_DUMMY_ERC1155_TO_DEPLOY)) {
 | 
				
			||||||
 | 
					            this._dummyTokenContracts.push(
 | 
				
			||||||
 | 
					                await ERC1155MintableContract.deployFrom0xArtifactAsync(
 | 
				
			||||||
 | 
					                    artifacts.ERC1155Mintable,
 | 
				
			||||||
 | 
					                    this._provider,
 | 
				
			||||||
 | 
					                    txDefaults,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return this._dummyTokenContracts;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public getProxyId(): string {
 | 
				
			||||||
 | 
					        this._validateProxyContractExistsOrThrow();
 | 
				
			||||||
 | 
					        return this._proxyIdIfExists as string;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async setBalancesAndAllowancesAsync(): Promise<ERC1155HoldingsByOwner> {
 | 
				
			||||||
 | 
					        this._validateDummyTokenContractsExistOrThrow();
 | 
				
			||||||
 | 
					        this._validateProxyContractExistsOrThrow();
 | 
				
			||||||
 | 
					        this._initialTokenIdsByOwner = {
 | 
				
			||||||
 | 
					            fungible: {} as ERC1155FungibleHoldingsByOwner,
 | 
				
			||||||
 | 
					            nonFungible: {}
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        const fungibleHoldingsByOwner:  ERC1155FungibleHoldingsByOwner = {};
 | 
				
			||||||
 | 
					        const nonFungibleHoldingsByOwner: ERC1155NonFungibleHoldingsByOwner = {};
 | 
				
			||||||
 | 
					        for (const dummyTokenContract of this._dummyTokenContracts) {
 | 
				
			||||||
 | 
					            // Fungible Tokens
 | 
				
			||||||
 | 
					            for (const i of _.times(constants.NUM_ERC1155_FUNGIBLE_TOKENS_MINT)) {
 | 
				
			||||||
 | 
					                // Create a fungible token
 | 
				
			||||||
 | 
					                const tokenUri = generatePseudoRandomSalt().toString();
 | 
				
			||||||
 | 
					                const tokenIsNonFungible = false;
 | 
				
			||||||
 | 
					                const tokenId = await this.createTokenAsync(dummyTokenContract.address, tokenUri, tokenIsNonFungible);
 | 
				
			||||||
 | 
					                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
 | 
				
			||||||
 | 
					                    await this.mintFungibleAsync(dummyTokenContract.address, tokenId, tokenOwnerAddress);
 | 
				
			||||||
 | 
					                    if (_.isUndefined(fungibleHoldingsByOwner[tokenOwnerAddress])) {
 | 
				
			||||||
 | 
					                        fungibleHoldingsByOwner[tokenOwnerAddress] = {};
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (_.isUndefined(fungibleHoldingsByOwner[tokenOwnerAddress][dummyTokenContract.address])) {
 | 
				
			||||||
 | 
					                        fungibleHoldingsByOwner[tokenOwnerAddress][dummyTokenContract.address] = {};
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    fungibleHoldingsByOwner[tokenOwnerAddress][dummyTokenContract.address][tokenIdAsString] = constants.INITIAL_ERC1155_FUNGIBLE_BALANCE;
 | 
				
			||||||
 | 
					                    await this.approveProxyAsync(dummyTokenContract.address, tokenId, tokenOwnerAddress);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // Non-Fungible Tokens
 | 
				
			||||||
 | 
					            for (const i of _.times(constants.NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT)) {
 | 
				
			||||||
 | 
					                const tokenUri = generatePseudoRandomSalt().toString();
 | 
				
			||||||
 | 
					                const tokenIsNonFungible = true;
 | 
				
			||||||
 | 
					                const tokenId = await this.createTokenAsync(dummyTokenContract.address, tokenUri, tokenIsNonFungible);
 | 
				
			||||||
 | 
					                const tokenIdAsString = tokenId.toString();
 | 
				
			||||||
 | 
					                this._nonFungibleTokenIds.push(tokenIdAsString);
 | 
				
			||||||
 | 
					                await this.mintNonFungibleAsync(dummyTokenContract.address, tokenId, this._tokenOwnerAddresses);
 | 
				
			||||||
 | 
					                let tokenNonce = 0;
 | 
				
			||||||
 | 
					                for (const tokenOwnerAddress of this._tokenOwnerAddresses) {
 | 
				
			||||||
 | 
					                     if (_.isUndefined(nonFungibleHoldingsByOwner[tokenOwnerAddress])) {
 | 
				
			||||||
 | 
					                        nonFungibleHoldingsByOwner[tokenOwnerAddress] = {};
 | 
				
			||||||
 | 
					                     }
 | 
				
			||||||
 | 
					                     if (_.isUndefined(nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyTokenContract.address])) {
 | 
				
			||||||
 | 
					                        nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyTokenContract.address] = {};
 | 
				
			||||||
 | 
					                     }
 | 
				
			||||||
 | 
					                     if (_.isUndefined(nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyTokenContract.address][tokenIdAsString])) {
 | 
				
			||||||
 | 
					                        nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyTokenContract.address][tokenIdAsString] = [];
 | 
				
			||||||
 | 
					                     }
 | 
				
			||||||
 | 
					                     const nonFungibleId = tokenId.plus(++tokenNonce);
 | 
				
			||||||
 | 
					                     this._nfts.push({id: nonFungibleId, tokenId});
 | 
				
			||||||
 | 
					                     nonFungibleHoldingsByOwner[tokenOwnerAddress][dummyTokenContract.address][tokenIdAsString].push(nonFungibleId);
 | 
				
			||||||
 | 
					                     await this.approveProxyAsync(dummyTokenContract.address, tokenId, tokenOwnerAddress);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this._initialTokenIdsByOwner = {
 | 
				
			||||||
 | 
					            fungible: fungibleHoldingsByOwner,
 | 
				
			||||||
 | 
					            nonFungible: nonFungibleHoldingsByOwner,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return this._initialTokenIdsByOwner;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async approveProxyAsync(tokenAddress: string, tokenId: BigNumber, tokenOwner: string): Promise<void> {
 | 
				
			||||||
 | 
					        const proxyAddress = (this._proxyContract as ERC1155ProxyContract).address;
 | 
				
			||||||
 | 
					        await this.approveProxyForAllAsync(proxyAddress, tokenAddress, tokenOwner);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async approveProxyForAllAsync(to: string, tokenAddress: string, tokenOwner: string): Promise<void> {
 | 
				
			||||||
 | 
					        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
				
			||||||
 | 
					        await this._web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					            await tokenContract.setApprovalForAll.sendTransactionAsync(to, true, {
 | 
				
			||||||
 | 
					                from: tokenOwner,
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async createTokenAsync(tokenAddress: string, tokenUri: string, tokenIsNonFungible: boolean): Promise<BigNumber> {
 | 
				
			||||||
 | 
					        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
				
			||||||
 | 
					        const txReceipt = await this._logDecoder.getTxWithDecodedLogsAsync(
 | 
				
			||||||
 | 
					            await tokenContract.create.sendTransactionAsync(tokenUri, tokenIsNonFungible),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        const createFungibleTokenLog = txReceipt.logs[0] as LogWithDecodedArgs<ERC1155MintableTransferSingleEventArgs>;
 | 
				
			||||||
 | 
					        const dummyFungibleTokenId = createFungibleTokenLog.args._id;
 | 
				
			||||||
 | 
					        return dummyFungibleTokenId;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async mintFungibleAsync(tokenAddress: string, tokenId: BigNumber, userAddress: string): Promise<void> {
 | 
				
			||||||
 | 
					        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
				
			||||||
 | 
					        await this._web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					            await tokenContract.mintFungible.sendTransactionAsync(
 | 
				
			||||||
 | 
					                tokenId,
 | 
				
			||||||
 | 
					                [userAddress],
 | 
				
			||||||
 | 
					                [constants.INITIAL_ERC1155_FUNGIBLE_BALANCE],
 | 
				
			||||||
 | 
					                { from: this._contractOwnerAddress }
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async mintNonFungibleAsync(tokenAddress: string, tokenId: BigNumber, userAddresses: string[]): Promise<void> {
 | 
				
			||||||
 | 
					        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
				
			||||||
 | 
					        await this._web3Wrapper.awaitTransactionSuccessAsync(
 | 
				
			||||||
 | 
					            await tokenContract.mintNonFungible.sendTransactionAsync(
 | 
				
			||||||
 | 
					                tokenId,
 | 
				
			||||||
 | 
					                userAddresses,
 | 
				
			||||||
 | 
					                { from: this._contractOwnerAddress }
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async ownerOfNonFungibleAsync(tokenAddress: string, tokenId: BigNumber): Promise<string> {
 | 
				
			||||||
 | 
					        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
				
			||||||
 | 
					        const owner = await tokenContract.ownerOf.callAsync(tokenId);
 | 
				
			||||||
 | 
					        return owner;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async isNonFungibleOwnerAsync(userAddress: string, tokenAddress: string, tokenId: BigNumber): Promise<boolean> {
 | 
				
			||||||
 | 
					        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
				
			||||||
 | 
					        const tokenOwner = await tokenContract.ownerOf.callAsync(tokenId);
 | 
				
			||||||
 | 
					        const isOwner = tokenOwner === userAddress;
 | 
				
			||||||
 | 
					        return isOwner;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async isProxyApprovedForAllAsync(userAddress: string, tokenAddress: string): Promise<boolean> {
 | 
				
			||||||
 | 
					        this._validateProxyContractExistsOrThrow();
 | 
				
			||||||
 | 
					        const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
				
			||||||
 | 
					        const operator = (this._proxyContract as ERC1155ProxyContract).address;
 | 
				
			||||||
 | 
					        const didApproveAll = await tokenContract.isApprovedForAll.callAsync(userAddress, operator);
 | 
				
			||||||
 | 
					        return didApproveAll;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public async getBalancesAsync(): Promise<ERC1155HoldingsByOwner> {
 | 
				
			||||||
 | 
					        this._validateDummyTokenContractsExistOrThrow();
 | 
				
			||||||
 | 
					        this._validateBalancesAndAllowancesSetOrThrow();
 | 
				
			||||||
 | 
					        const tokenHoldingsByOwner: ERC1155FungibleHoldingsByOwner = {};
 | 
				
			||||||
 | 
					        const nonFungibleHoldingsByOwner: ERC1155NonFungibleHoldingsByOwner = {};
 | 
				
			||||||
 | 
					        for (const dummyTokenContract of this._dummyTokenContracts) {
 | 
				
			||||||
 | 
					            const tokenAddress = dummyTokenContract.address;
 | 
				
			||||||
 | 
					            const tokenContract = this._getTokenContractFromAssetData(tokenAddress);
 | 
				
			||||||
 | 
					            // 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 tokenContract.balanceOfBatch.callAsync(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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    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 getTokenAddresses(): string[] {
 | 
				
			||||||
 | 
					        const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address);
 | 
				
			||||||
 | 
					        return tokenAddresses;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    private _getTokenContractFromAssetData(tokenAddress: string): ERC1155MintableContract {
 | 
				
			||||||
 | 
					        const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
 | 
				
			||||||
 | 
					        if (_.isUndefined(tokenContractIfExists)) {
 | 
				
			||||||
 | 
					            throw new Error(`Token: ${tokenAddress} was not deployed through ERC1155Wrapper`);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return tokenContractIfExists;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    private _validateDummyTokenContractsExistOrThrow(): void {
 | 
				
			||||||
 | 
					        if (_.isUndefined(this._dummyTokenContracts)) {
 | 
				
			||||||
 | 
					            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_wrapper';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,9 @@
 | 
				
			|||||||
    "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/DummyERC1155Receiver.json",
 | 
				
			||||||
 | 
					        "generated-artifacts/ERC1155Mintable.json",
 | 
				
			||||||
 | 
					        "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",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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_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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,6 +94,18 @@ export const assetDataUtils = {
 | 
				
			|||||||
        const assetData = abiEncoder.encode(args, encodingRules);
 | 
					        const assetData = abiEncoder.encode(args, encodingRules);
 | 
				
			||||||
        return assetData;
 | 
					        return assetData;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Encodes assetData for multiple AssetProxies into a single hex encoded assetData string, usable in the makerAssetData or
 | 
				
			||||||
 | 
					     * takerAssetData fields in a 0x order.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     * @return The hex encoded assetData string
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    encodeERC1155AssetData(tokenAddress: string, tokenIds: BigNumber[], tokenValues: BigNumber[], callbackData: string): string {
 | 
				
			||||||
 | 
					        const abiEncoder = AbiEncoder.createMethod('ERC1155Token', ['address','uint256[]','uint256[]','bytes']);
 | 
				
			||||||
 | 
					        const args = [tokenAddress, tokenIds, tokenValues, callbackData];
 | 
				
			||||||
 | 
					        const assetData = abiEncoder.encode(args, encodingRules);
 | 
				
			||||||
 | 
					        return assetData;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Decodes a MultiAsset assetData hex string into it's corresponding amounts and nestedAssetData
 | 
					     * Decodes a MultiAsset assetData hex string into it's corresponding amounts and nestedAssetData
 | 
				
			||||||
     * @param assetData Hex encoded assetData string to decode
 | 
					     * @param assetData Hex encoded assetData string to decode
 | 
				
			||||||
@@ -174,6 +186,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}`);
 | 
				
			||||||
@@ -201,6 +214,9 @@ export const assetDataUtils = {
 | 
				
			|||||||
    isMultiAssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is MultiAssetData {
 | 
					    isMultiAssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is MultiAssetData {
 | 
				
			||||||
        return decodedAssetData.assetProxyId === AssetProxyId.MultiAsset;
 | 
					        return decodedAssetData.assetProxyId === AssetProxyId.MultiAsset;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    isER1155AssetData(decodedAssetData: SingleAssetData | MultiAssetData): decodedAssetData is MultiAssetData {
 | 
				
			||||||
 | 
					        return decodedAssetData.assetProxyId === AssetProxyId.MultiAsset;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Throws if the length or assetProxyId are invalid for the ERC20Proxy.
 | 
					     * Throws if the length or assetProxyId are invalid for the ERC20Proxy.
 | 
				
			||||||
     * @param assetData Hex encoded assetData string
 | 
					     * @param assetData Hex encoded assetData string
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,15 @@ 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 type SingleAssetData = ERC20AssetData | ERC721AssetData | ERC1155AssetData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface MultiAssetData {
 | 
					export interface MultiAssetData {
 | 
				
			||||||
    assetProxyId: string;
 | 
					    assetProxyId: string;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user