From 5063c17e6bfbef396a121eb3b1a2eecee0fb488f Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 5 Mar 2019 08:52:33 -0800 Subject: [PATCH 01/10] ERC1155 Asset Data tests + types --- packages/order-utils/src/asset_data_utils.ts | 3 +++ packages/order-utils/test/asset_data_utils_test.ts | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/packages/order-utils/src/asset_data_utils.ts b/packages/order-utils/src/asset_data_utils.ts index 2acf57d5f6..1dc6922365 100644 --- a/packages/order-utils/src/asset_data_utils.ts +++ b/packages/order-utils/src/asset_data_utils.ts @@ -5,6 +5,9 @@ import { ERC1155AssetDataNoProxyId, ERC20AssetData, ERC721AssetData, + ERC1155AssetData, + ERC1155AssetDataAbi, + ERC1155AssetDataNoProxyId, MultiAssetData, MultiAssetDataWithRecursiveDecoding, SingleAssetData, diff --git a/packages/order-utils/test/asset_data_utils_test.ts b/packages/order-utils/test/asset_data_utils_test.ts index 2634e7f595..d0206b1aa0 100644 --- a/packages/order-utils/test/asset_data_utils_test.ts +++ b/packages/order-utils/test/asset_data_utils_test.ts @@ -64,7 +64,11 @@ describe('assetDataUtils', () => { KNOWN_ERC1155_ENCODING.tokenAddress, KNOWN_ERC1155_ENCODING.tokenIds, KNOWN_ERC1155_ENCODING.tokenValues, +<<<<<<< HEAD KNOWN_ERC1155_ENCODING.callbackData, +======= + KNOWN_ERC1155_ENCODING.callbackData +>>>>>>> 5bddc5795... ERC1155 Asset Data tests + types ); expect(assetData).to.equal(KNOWN_ERC1155_ENCODING.assetData); }); From 82b6dad1bad503a44d913e14c6240343f54fbdd0 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 4 Mar 2019 18:12:45 -0800 Subject: [PATCH 02/10] Exchange Integration Tests --- contracts/exchange/test/core.ts | 399 ++++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) diff --git a/contracts/exchange/test/core.ts b/contracts/exchange/test/core.ts index 7acb4e2aba..44961576a2 100644 --- a/contracts/exchange/test/core.ts +++ b/contracts/exchange/test/core.ts @@ -5,6 +5,7 @@ import { ERC721ProxyContract, ERC721Wrapper, MultiAssetProxyContract, + ERC1155ProxyWrapper, } from '@0x/contracts-asset-proxy'; import { artifacts as erc20Artifacts, @@ -26,6 +27,7 @@ import { txDefaults, web3Wrapper, } from '@0x/contracts-test-utils'; +import { ERC1155MintableContract, DummyERC1155ReceiverBatchTokenReceivedEventArgs } from '@0x/contracts-erc1155'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; @@ -44,6 +46,8 @@ import { ReentrantERC20TokenContract, TestStaticCallReceiverContract, } from '../src'; +import { Erc1155Wrapper, ERC1155Contract } from '../../erc1155/lib/src'; +import { Exception } from 'handlebars'; chaiSetup.configure(); const expect = chai.expect; @@ -64,19 +68,26 @@ describe('Exchange core', () => { let exchange: ExchangeContract; let erc20Proxy: ERC20ProxyContract; let erc721Proxy: ERC721ProxyContract; + let erc1155Proxy: ERC721ProxyContract; let multiAssetProxy: MultiAssetProxyContract; let maliciousWallet: TestStaticCallReceiverContract; let maliciousValidator: TestStaticCallReceiverContract; + let erc1155Contract: ERC1155MintableContract; let signedOrder: SignedOrder; let erc20Balances: ERC20BalancesByOwner; let exchangeWrapper: ExchangeWrapper; let erc20Wrapper: ERC20Wrapper; let erc721Wrapper: ERC721Wrapper; + let erc1155Wrapper: Erc1155Wrapper; + let erc1155ProxyWrapper: ERC1155ProxyWrapper; let orderFactory: OrderFactory; let erc721MakerAssetIds: BigNumber[]; let erc721TakerAssetIds: BigNumber[]; + let erc1155FungibleTokens: BigNumber[]; + let erc1155NonFungibleTokensOwnedByMaker: BigNumber[]; + let erc1155NonFungibleTokensOwnedByTaker: BigNumber[]; let defaultMakerAssetAddress: string; let defaultTakerAssetAddress: string; @@ -93,6 +104,7 @@ describe('Exchange core', () => { erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner); + erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner); // Deploy AssetProxies, Exchange, tokens, and malicious contracts erc20Proxy = await erc20Wrapper.deployProxyAsync(); @@ -108,6 +120,9 @@ describe('Exchange core', () => { constants.DUMMY_TOKEN_DECIMALS, ); [erc721Token] = await erc721Wrapper.deployDummyTokensAsync(); + erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync(); + [erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyTokensAsync(); + erc1155Contract = erc1155Wrapper.getContract(); exchange = await ExchangeContract.deployFrom0xArtifactAsync( artifacts.Exchange, provider, @@ -154,6 +169,20 @@ describe('Exchange core', () => { constants.AWAIT_TRANSACTION_MINED_MS, ); + // Configure ERC1155Proxy + await web3Wrapper.awaitTransactionSuccessAsync( + await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { + 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 await web3Wrapper.awaitTransactionSuccessAsync( await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { @@ -178,6 +207,7 @@ describe('Exchange core', () => { exchangeWrapper = new ExchangeWrapper(exchange, provider); await exchangeWrapper.registerAssetProxyAsync(erc20Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(erc721Proxy.address, owner); + await exchangeWrapper.registerAssetProxyAsync(erc1155Proxy.address, owner); await exchangeWrapper.registerAssetProxyAsync(multiAssetProxy.address, owner); // Configure ERC20 tokens @@ -189,6 +219,21 @@ describe('Exchange core', () => { erc721MakerAssetIds = erc721Balances[makerAddress][erc721Token.address]; erc721TakerAssetIds = erc721Balances[takerAddress][erc721Token.address]; + // Configure ERC1155 tokens + await erc1155ProxyWrapper.setBalancesAndAllowancesAsync(); + erc1155FungibleTokens = erc1155ProxyWrapper.getFungibleTokenIds(); + const nonFungibleTokens = erc1155ProxyWrapper.getNonFungibleTokenIds(); + const tokenBalances = await erc1155ProxyWrapper.getBalancesAsync(); + erc1155NonFungibleTokensOwnedByMaker = []; + erc1155NonFungibleTokensOwnedByTaker = []; + _.each(nonFungibleTokens, (nonFungibleToken: BigNumber) => { + const nonFungibleTokenAsString = nonFungibleToken.toString(); + const nonFungibleTokenHeldByMaker = tokenBalances.nonFungible[makerAddress][erc1155Contract.address][nonFungibleTokenAsString][0]; + erc1155NonFungibleTokensOwnedByMaker.push(nonFungibleTokenHeldByMaker); + const nonFungibleTokenHeldByTaker = tokenBalances.nonFungible[takerAddress][erc1155Contract.address][nonFungibleTokenAsString][0]; + erc1155NonFungibleTokensOwnedByTaker.push(nonFungibleTokenHeldByTaker); + }); + // Configure order defaults defaultMakerAssetAddress = erc20TokenA.address; defaultTakerAssetAddress = erc20TokenB.address; @@ -1041,6 +1086,360 @@ describe('Exchange core', () => { }); }); + describe.only('Testing exchange of erc1155 assets', () => { + it('should allow a single fungible erc1155 asset to be exchanged for another', async () => { + // setup test parameters + const tokenHolders = [makerAddress, takerAddress]; + const makerAssetsToTransfer = erc1155FungibleTokens.slice(0, 1); + const takerAssetsToTransfer = erc1155FungibleTokens.slice(1, 2); + const makerValuesToTransfer = [new BigNumber(500)]; + const takerValuesToTransfer = [new BigNumber(200)]; + const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); + const makerAssetAmount = new BigNumber(1); + const takerAssetAmount = new BigNumber(1); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount)}); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount)}); + const receiverCallbackData = '0x'; + const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); + const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + signedOrder = await orderFactory.newSignedOrderAsync({ + makerAssetData, + takerAssetData, + makerAssetAmount, + takerAssetAmount, + makerFee: constants.ZERO_AMOUNT, + takerFee: constants.ZERO_AMOUNT, + }); + const takerAssetFillAmount = new BigNumber(1); + // check balances before transfer + const expectedInitialBalances = [ + // makerAddress / makerToken + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / takerToken + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / makerToken + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / takerToken + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // execute transfer + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { + takerAssetFillAmount, + }); + // check balances after transfer + const expectedFinalBalances = [ + // makerAddress / makerToken + expectedInitialBalances[0].minus(totalMakerValuesTransferred[0]), + // makerAddress / takerToken + expectedInitialBalances[1].plus(totalTakerValuesTransferred[0]), + // takerAddress / makerToken + expectedInitialBalances[2].plus(totalMakerValuesTransferred[0]), + // takerAddress / takerToken + expectedInitialBalances[3].minus(totalTakerValuesTransferred[0]), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); + it('should allow a single non-fungible erc1155 asset to be exchanged for another', async () => { + // setup test parameters + const tokenHolders = [makerAddress, takerAddress]; + const makerAssetsToTransfer = erc1155NonFungibleTokensOwnedByMaker.slice(0, 1); + const takerAssetsToTransfer = erc1155NonFungibleTokensOwnedByTaker.slice(0, 1); + const makerValuesToTransfer = [new BigNumber(1)]; + const takerValuesToTransfer = [new BigNumber(1)]; + const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); + const makerAssetAmount = new BigNumber(1); + const takerAssetAmount = new BigNumber(1); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount)}); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount)}); + const receiverCallbackData = '0x'; + const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); + const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + signedOrder = await orderFactory.newSignedOrderAsync({ + makerAssetData, + takerAssetData, + makerAssetAmount, + takerAssetAmount, + makerFee: constants.ZERO_AMOUNT, + takerFee: constants.ZERO_AMOUNT, + }); + const takerAssetFillAmount = new BigNumber(1); + // check balances before transfer + const nftOwnerBalance = new BigNumber(1); + const nftNotOwnerBalance = new BigNumber(0); + const expectedInitialBalances = [ + // makerAddress / makerToken + nftOwnerBalance, + // makerAddress / takerToken + nftNotOwnerBalance, + // takerAddress / makerToken + nftNotOwnerBalance, + // takerAddress / takerToken + nftOwnerBalance, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // execute transfer + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { + takerAssetFillAmount, + }); + // check balances after transfer + const expectedFinalBalances = [ + // makerAddress / makerToken + expectedInitialBalances[0].minus(totalMakerValuesTransferred[0]), + // makerAddress / takerToken + expectedInitialBalances[1].plus(totalTakerValuesTransferred[0]), + // takerAddress / makerToken + expectedInitialBalances[2].plus(totalMakerValuesTransferred[0]), + // takerAddress / takerToken + expectedInitialBalances[3].minus(totalTakerValuesTransferred[0]), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); + it('should allow multiple erc1155 assets to be exchanged for a single asset', async () => { + // setup test parameters + const tokenHolders = [makerAddress, takerAddress]; + const makerAssetsToTransfer = erc1155FungibleTokens.slice(0, 3); + const takerAssetsToTransfer = erc1155NonFungibleTokensOwnedByTaker.slice(0, 1); + const makerValuesToTransfer = [new BigNumber(500), new BigNumber(700), new BigNumber(900)]; + const takerValuesToTransfer = [new BigNumber(1)]; + const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); + const makerAssetAmount = new BigNumber(1); + const takerAssetAmount = new BigNumber(1); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount)}); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount)}); + const receiverCallbackData = '0x'; + const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); + const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + signedOrder = await orderFactory.newSignedOrderAsync({ + makerAssetData, + takerAssetData, + makerAssetAmount, + takerAssetAmount, + makerFee: constants.ZERO_AMOUNT, + takerFee: constants.ZERO_AMOUNT, + }); + const takerAssetFillAmount = new BigNumber(1); + // check balances before transfer + const nftOwnerBalance = new BigNumber(1); + const nftNotOwnerBalance = new BigNumber(0); + const expectedInitialBalances = [ + // makerAddress / makerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / makerToken[1] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / makerToken[2] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / takerToken + nftNotOwnerBalance, + // takerAddress / makerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / makerToken[1] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / makerToken[2] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / takerToken + nftOwnerBalance, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // execute transfer + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { + takerAssetFillAmount, + }); + // check balances after transfer + const expectedFinalBalances = [ + // makerAddress / makerToken[0] + expectedInitialBalances[0].minus(totalMakerValuesTransferred[0]), + // makerAddress / makerToken[1] + expectedInitialBalances[1].minus(totalMakerValuesTransferred[1]), + // makerAddress / makerToken[2] + expectedInitialBalances[2].minus(totalMakerValuesTransferred[2]), + // makerAddress / takerToken + expectedInitialBalances[3].plus(totalTakerValuesTransferred[0]), + // takerAddress / makerToken[0] + expectedInitialBalances[4].plus(totalMakerValuesTransferred[0]), + // takerAddress / makerToken[1] + expectedInitialBalances[5].plus(totalMakerValuesTransferred[1]), + // takerAddress / makerToken[2] + expectedInitialBalances[6].plus(totalMakerValuesTransferred[2]), + // takerAddress / takerToken + expectedInitialBalances[7].minus(totalTakerValuesTransferred[0]), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); + it('should allow multiple erc1155 assets to be exchanged for multiple erc1155 assets, mixed fungible/non-fungible', async () => { + // setup test parameters + // the maker is trading two fungibles & one non-fungible + // the taker is trading one fungible & two non-fungibles + const tokenHolders = [makerAddress, takerAddress]; + const makerFungibleAssetsToTransfer = erc1155FungibleTokens.slice(0, 2); + const makerNonFungibleAssetsToTransfer = erc1155NonFungibleTokensOwnedByMaker.slice(0, 1); + const makerAssetsToTransfer = makerFungibleAssetsToTransfer.concat(makerNonFungibleAssetsToTransfer); + const takerFungibleAssetsToTransfer = erc1155FungibleTokens.slice(2, 3); + const takerNonFungibleAssetsToTransfer = erc1155NonFungibleTokensOwnedByTaker.slice(0, 2); + const takerAssetsToTransfer = takerFungibleAssetsToTransfer.concat(takerNonFungibleAssetsToTransfer); + const makerValuesToTransfer = [new BigNumber(500), new BigNumber(700), new BigNumber(1)]; + const takerValuesToTransfer = [new BigNumber(900), new BigNumber(1), new BigNumber(1)]; + const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); + const makerAssetAmount = new BigNumber(1); + const takerAssetAmount = new BigNumber(1); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount)}); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount)}); + const receiverCallbackData = '0x'; + const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); + const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + signedOrder = await orderFactory.newSignedOrderAsync({ + makerAssetData, + takerAssetData, + makerAssetAmount, + takerAssetAmount, + makerFee: constants.ZERO_AMOUNT, + takerFee: constants.ZERO_AMOUNT, + }); + const takerAssetFillAmount = new BigNumber(1); + // check balances before transfer + const nftOwnerBalance = new BigNumber(1); + const nftNotOwnerBalance = new BigNumber(0); + const expectedInitialBalances = [ + // makerAddress / makerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / makerToken[1] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / makerToken[2] + nftOwnerBalance, + // makerAddress / takerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / takerToken[1] + nftNotOwnerBalance, + // makerAddress / takerToken[2] + nftNotOwnerBalance, + // takerAddress / makerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / makerToken[1] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / makerToken[2] + nftNotOwnerBalance, + // takerAddress / takerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / takerToken[1] + nftOwnerBalance, + // takerAddress / takerToken[2] + nftOwnerBalance, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // execute transfer + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { + takerAssetFillAmount, + }); + // check balances after transfer + const expectedFinalBalances = [ + // makerAddress / makerToken[0] + expectedInitialBalances[0].minus(totalMakerValuesTransferred[0]), + // makerAddress / makerToken[1] + expectedInitialBalances[1].minus(totalMakerValuesTransferred[1]), + // makerAddress / makerToken[2] + expectedInitialBalances[2].minus(totalMakerValuesTransferred[2]), + // makerAddress / takerToken[0] + expectedInitialBalances[3].plus(totalTakerValuesTransferred[0]), + // makerAddress / takerToken[1] + expectedInitialBalances[4].plus(totalTakerValuesTransferred[1]), + // makerAddress / takerToken[2] + expectedInitialBalances[5].plus(totalTakerValuesTransferred[2]), + // takerAddress / makerToken[0] + expectedInitialBalances[6].plus(totalMakerValuesTransferred[0]), + // takerAddress / makerToken[1] + expectedInitialBalances[7].plus(totalMakerValuesTransferred[1]), + // takerAddress / makerToken[2] + expectedInitialBalances[8].plus(totalMakerValuesTransferred[2]), + // takerAddress / takerToken[0] + expectedInitialBalances[9].minus(totalTakerValuesTransferred[0]), + // takerAddress / takerToken[1] + expectedInitialBalances[10].minus(totalTakerValuesTransferred[1]), + // takerAddress / takerToken[2] + expectedInitialBalances[11].minus(totalTakerValuesTransferred[2]), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); + it('should allow an order exchanging erc1155 assets to be partially filled', async () => { + // NOTICE: + // As-per the eip1155 standard, there is no way to distinguish between a fungible or non-fungible erc1155 assets. + // Hence we cannot force partial fills to fail if there is a non-fungible asset (which should be fill or kill). + // We considered encoding whether an asset is fungible/non-fungible in erc1155 assetData, but + // this is no more robust than a simple check by the client. Enforcing this at the smart contract level + // is something that could be done with the upcoming static call proxy. + // + // setup test parameters + // the maker is trading two fungibles and the taker is trading one fungible + // note that this will result in a partial fill because the `takerAssetAmount` + // less than the `takerAssetAmount` of the order. + const takerAssetFillAmount = new BigNumber(6); + const tokenHolders = [makerAddress, takerAddress]; + const makerAssetsToTransfer = erc1155FungibleTokens.slice(0, 2); + const takerAssetsToTransfer = erc1155FungibleTokens.slice(2, 3); + const makerValuesToTransfer = [new BigNumber(500), new BigNumber(700)]; + const takerValuesToTransfer = [new BigNumber(900)]; + const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); + const makerAssetAmount = new BigNumber(10); + const takerAssetAmount = new BigNumber(20); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount).times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount)}); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount).times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount)}); + const receiverCallbackData = '0x'; + const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); + const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + signedOrder = await orderFactory.newSignedOrderAsync({ + makerAssetData, + takerAssetData, + makerAssetAmount, + takerAssetAmount, + makerFee: constants.ZERO_AMOUNT, + takerFee: constants.ZERO_AMOUNT, + }); + // check balances before transfer + const expectedInitialBalances = [ + // makerAddress / makerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / makerToken[1] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // makerAddress / takerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / makerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / makerToken[1] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // takerAddress / takerToken[0] + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // execute transfer + await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { + takerAssetFillAmount, + }); + // check balances after transfer + const expectedFinalBalances = [ + // makerAddress / makerToken[0] + expectedInitialBalances[0].minus(totalMakerValuesTransferred[0]), + // makerAddress / makerToken[1] + expectedInitialBalances[1].minus(totalMakerValuesTransferred[1]), + // makerAddress / takerToken[0] + expectedInitialBalances[2].plus(totalTakerValuesTransferred[0]), + // takerAddress / makerToken[0] + expectedInitialBalances[3].plus(totalMakerValuesTransferred[0]), + // takerAddress / makerToken[1] + expectedInitialBalances[4].plus(totalMakerValuesTransferred[1]), + // takerAddress / takerToken[0] + expectedInitialBalances[5].minus(totalTakerValuesTransferred[0]), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + // check that the order is partially filled + const orderInfo = await exchangeWrapper.getOrderInfoAsync(signedOrder); + const expectedOrderHash = orderHashUtils.getOrderHashHex(signedOrder); + const expectedTakerAssetFilledAmount = takerAssetFillAmount; + const expectedOrderStatus = OrderStatus.Fillable; + expect(orderInfo.orderHash).to.be.equal(expectedOrderHash); + expect(orderInfo.orderTakerAssetFilledAmount).to.be.bignumber.equal(expectedTakerAssetFilledAmount); + expect(orderInfo.orderStatus).to.equal(expectedOrderStatus); + }); + }); + describe('getOrderInfo', () => { beforeEach(async () => { signedOrder = await orderFactory.newSignedOrderAsync(); From 31dbca7efcd0746961a1d9fe97bcebb2b41a42d1 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Mar 2019 15:47:54 -0800 Subject: [PATCH 03/10] More integration tests for ERC1155 <> Multi Asset Proxy encoding / decoding --- contracts/exchange/test/core.ts | 144 ++++++++++++++---- .../order-utils/test/asset_data_utils_test.ts | 79 +++++++--- 2 files changed, 170 insertions(+), 53 deletions(-) diff --git a/contracts/exchange/test/core.ts b/contracts/exchange/test/core.ts index 44961576a2..53d6b1d028 100644 --- a/contracts/exchange/test/core.ts +++ b/contracts/exchange/test/core.ts @@ -169,8 +169,8 @@ describe('Exchange core', () => { constants.AWAIT_TRANSACTION_MINED_MS, ); - // Configure ERC1155Proxy - await web3Wrapper.awaitTransactionSuccessAsync( + // Configure ERC1155Proxy + await web3Wrapper.awaitTransactionSuccessAsync( await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: owner, }), @@ -228,9 +228,11 @@ describe('Exchange core', () => { erc1155NonFungibleTokensOwnedByTaker = []; _.each(nonFungibleTokens, (nonFungibleToken: BigNumber) => { const nonFungibleTokenAsString = nonFungibleToken.toString(); - const nonFungibleTokenHeldByMaker = tokenBalances.nonFungible[makerAddress][erc1155Contract.address][nonFungibleTokenAsString][0]; + const nonFungibleTokenHeldByMaker = + tokenBalances.nonFungible[makerAddress][erc1155Contract.address][nonFungibleTokenAsString][0]; erc1155NonFungibleTokensOwnedByMaker.push(nonFungibleTokenHeldByMaker); - const nonFungibleTokenHeldByTaker = tokenBalances.nonFungible[takerAddress][erc1155Contract.address][nonFungibleTokenAsString][0]; + const nonFungibleTokenHeldByTaker = + tokenBalances.nonFungible[takerAddress][erc1155Contract.address][nonFungibleTokenAsString][0]; erc1155NonFungibleTokensOwnedByTaker.push(nonFungibleTokenHeldByTaker); }); @@ -1097,11 +1099,25 @@ describe('Exchange core', () => { const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); const makerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1); - const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount)}); - const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount)}); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => { + return value.times(makerAssetAmount); + }); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => { + return value.times(takerAssetAmount); + }); const receiverCallbackData = '0x'; - const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); - const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + const makerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + makerAssetsToTransfer, + makerValuesToTransfer, + receiverCallbackData, + ); + const takerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + takerAssetsToTransfer, + takerValuesToTransfer, + receiverCallbackData, + ); signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData, takerAssetData, @@ -1114,9 +1130,9 @@ describe('Exchange core', () => { // check balances before transfer const expectedInitialBalances = [ // makerAddress / makerToken - constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / takerToken - constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // takerAddress / makerToken constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // takerAddress / takerToken @@ -1150,11 +1166,25 @@ describe('Exchange core', () => { const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); const makerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1); - const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount)}); - const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount)}); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => { + return value.times(makerAssetAmount); + }); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => { + return value.times(takerAssetAmount); + }); const receiverCallbackData = '0x'; - const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); - const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + const makerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + makerAssetsToTransfer, + makerValuesToTransfer, + receiverCallbackData, + ); + const takerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + takerAssetsToTransfer, + takerValuesToTransfer, + receiverCallbackData, + ); signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData, takerAssetData, @@ -1171,7 +1201,7 @@ describe('Exchange core', () => { // makerAddress / makerToken nftOwnerBalance, // makerAddress / takerToken - nftNotOwnerBalance, + nftNotOwnerBalance, // takerAddress / makerToken nftNotOwnerBalance, // takerAddress / takerToken @@ -1205,11 +1235,25 @@ describe('Exchange core', () => { const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); const makerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1); - const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount)}); - const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount)}); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => { + return value.times(makerAssetAmount); + }); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => { + return value.times(takerAssetAmount); + }); const receiverCallbackData = '0x'; - const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); - const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + const makerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + makerAssetsToTransfer, + makerValuesToTransfer, + receiverCallbackData, + ); + const takerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + takerAssetsToTransfer, + takerValuesToTransfer, + receiverCallbackData, + ); signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData, takerAssetData, @@ -1224,11 +1268,11 @@ describe('Exchange core', () => { const nftNotOwnerBalance = new BigNumber(0); const expectedInitialBalances = [ // makerAddress / makerToken[0] - constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / makerToken[1] - constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / makerToken[2] - constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / takerToken nftNotOwnerBalance, // takerAddress / makerToken[0] @@ -1282,11 +1326,25 @@ describe('Exchange core', () => { const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); const makerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1); - const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount)}); - const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount)}); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => { + return value.times(makerAssetAmount); + }); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => { + return value.times(takerAssetAmount); + }); const receiverCallbackData = '0x'; - const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); - const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + const makerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + makerAssetsToTransfer, + makerValuesToTransfer, + receiverCallbackData, + ); + const takerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + takerAssetsToTransfer, + takerValuesToTransfer, + receiverCallbackData, + ); signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData, takerAssetData, @@ -1301,11 +1359,11 @@ describe('Exchange core', () => { const nftNotOwnerBalance = new BigNumber(0); const expectedInitialBalances = [ // makerAddress / makerToken[0] - constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / makerToken[1] constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / makerToken[2] - nftOwnerBalance, + nftOwnerBalance, // makerAddress / takerToken[0] constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / takerToken[1] @@ -1380,11 +1438,31 @@ describe('Exchange core', () => { const tokensToTransfer = makerAssetsToTransfer.concat(takerAssetsToTransfer); const makerAssetAmount = new BigNumber(10); const takerAssetAmount = new BigNumber(20); - const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => {return value.times(makerAssetAmount).times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount)}); - const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => {return value.times(takerAssetAmount).times(takerAssetFillAmount).dividedToIntegerBy(takerAssetAmount)}); + const totalMakerValuesTransferred = _.map(makerValuesToTransfer, (value: BigNumber) => { + return value + .times(makerAssetAmount) + .times(takerAssetFillAmount) + .dividedToIntegerBy(takerAssetAmount); + }); + const totalTakerValuesTransferred = _.map(takerValuesToTransfer, (value: BigNumber) => { + return value + .times(takerAssetAmount) + .times(takerAssetFillAmount) + .dividedToIntegerBy(takerAssetAmount); + }); const receiverCallbackData = '0x'; - const makerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, makerAssetsToTransfer, makerValuesToTransfer, receiverCallbackData); - const takerAssetData = assetDataUtils.encodeERC1155AssetData(erc1155Contract.address, takerAssetsToTransfer, takerValuesToTransfer, receiverCallbackData); + const makerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + makerAssetsToTransfer, + makerValuesToTransfer, + receiverCallbackData, + ); + const takerAssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + takerAssetsToTransfer, + takerValuesToTransfer, + receiverCallbackData, + ); signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData, takerAssetData, @@ -1396,7 +1474,7 @@ describe('Exchange core', () => { // check balances before transfer const expectedInitialBalances = [ // makerAddress / makerToken[0] - constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / makerToken[1] constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, // makerAddress / takerToken[0] diff --git a/packages/order-utils/test/asset_data_utils_test.ts b/packages/order-utils/test/asset_data_utils_test.ts index d0206b1aa0..a9cdcf44f2 100644 --- a/packages/order-utils/test/asset_data_utils_test.ts +++ b/packages/order-utils/test/asset_data_utils_test.ts @@ -1,6 +1,6 @@ import * as chai from 'chai'; -import { AssetProxyId, ERC721AssetData } from '@0x/types'; +import { AssetProxyId, ERC1155AssetData, ERC721AssetData } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { assetDataUtils } from '../src/asset_data_utils'; @@ -30,10 +30,14 @@ const KNOWN_ERC1155_ENCODING = { '0x9645780d0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000', }; const KNOWN_MULTI_ASSET_ENCODING = { - amounts: [new BigNumber(1), new BigNumber(1)], - nestedAssetData: [KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC721_ENCODING.assetData], + amounts: [new BigNumber(70), new BigNumber(1), new BigNumber(18)], + nestedAssetData: [ + KNOWN_ERC20_ENCODING.assetData, + KNOWN_ERC721_ENCODING.assetData, + KNOWN_ERC1155_ENCODING.assetData, + ], assetData: - '0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000', + '0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002049645780d0000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', }; describe('assetDataUtils', () => { @@ -80,14 +84,14 @@ describe('assetDataUtils', () => { expect(decodedAssetData.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds); expect(decodedAssetData.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData); }); - it('should encode ERC20 and ERC721 multiAssetData', () => { + it('should encode ERC20, ERC721 and ERC1155 multiAssetData', () => { const assetData = assetDataUtils.encodeMultiAssetData( KNOWN_MULTI_ASSET_ENCODING.amounts, KNOWN_MULTI_ASSET_ENCODING.nestedAssetData, ); expect(assetData).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData); }); - it('should decode ERC20 and ERC721 multiAssetData', () => { + it('should decode ERC20, ERC721 and ERC1155 multiAssetData', () => { const decodedAssetData = assetDataUtils.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData); expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset); expect(decodedAssetData.amounts).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.amounts); @@ -97,44 +101,79 @@ describe('assetDataUtils', () => { const decodedAssetData = assetDataUtils.decodeMultiAssetDataRecursively(KNOWN_MULTI_ASSET_ENCODING.assetData); expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset); expect(decodedAssetData.amounts).to.deep.equal(KNOWN_MULTI_ASSET_ENCODING.amounts); + expect(decodedAssetData.nestedAssetData.length).to.equal(3); const decodedErc20AssetData = decodedAssetData.nestedAssetData[0]; - // tslint:disable-next-line:no-unnecessary-type-assertion - const decodedErc721AssetData = decodedAssetData.nestedAssetData[1] as ERC721AssetData; expect(decodedErc20AssetData.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address); expect(decodedErc20AssetData.assetProxyId).to.equal(AssetProxyId.ERC20); + // tslint:disable-next-line:no-unnecessary-type-assertion + const decodedErc721AssetData = decodedAssetData.nestedAssetData[1] as ERC721AssetData; expect(decodedErc721AssetData.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address); expect(decodedErc721AssetData.assetProxyId).to.equal(AssetProxyId.ERC721); expect(decodedErc721AssetData.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId); + // tslint:disable-next-line:no-unnecessary-type-assertion + const decodedErc1155AssetData = decodedAssetData.nestedAssetData[2] as ERC1155AssetData; + expect(decodedErc1155AssetData.tokenAddress).to.be.equal(KNOWN_ERC1155_ENCODING.tokenAddress); + expect(decodedErc1155AssetData.tokenValues).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenValues); + expect(decodedErc1155AssetData.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds); + expect(decodedErc1155AssetData.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData); }); it('should recursively decode nested assetData within multiAssetData', () => { - const amounts = [new BigNumber(1), new BigNumber(1), new BigNumber(2)]; + // setup test parameters + const erc20Amount = new BigNumber(1); + const erc721Amount = new BigNumber(1); + const erc1155Amount = new BigNumber(15); + const nestedAssetsAmount = new BigNumber(2); + const amounts = [erc20Amount, erc721Amount, erc1155Amount, nestedAssetsAmount]; const nestedAssetData = [ KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC721_ENCODING.assetData, + KNOWN_ERC1155_ENCODING.assetData, KNOWN_MULTI_ASSET_ENCODING.assetData, ]; const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); + // execute test const decodedAssetData = assetDataUtils.decodeMultiAssetDataRecursively(assetData); + // validate asset data expect(decodedAssetData.assetProxyId).to.equal(AssetProxyId.MultiAsset); - const expectedAmounts = [new BigNumber(1), new BigNumber(1), new BigNumber(2), new BigNumber(2)]; + const expectedAmounts = [ + erc20Amount, + erc721Amount, + erc1155Amount, + KNOWN_MULTI_ASSET_ENCODING.amounts[0].times(nestedAssetsAmount), + KNOWN_MULTI_ASSET_ENCODING.amounts[1].times(nestedAssetsAmount), + KNOWN_MULTI_ASSET_ENCODING.amounts[2].times(nestedAssetsAmount), + ]; expect(decodedAssetData.amounts).to.deep.equal(expectedAmounts); - const expectedLength = 4; - expect(decodedAssetData.nestedAssetData.length).to.be.equal(expectedLength); - const decodedErc20AssetData1 = decodedAssetData.nestedAssetData[0]; - // tslint:disable-next-line:no-unnecessary-type-assertion - const decodedErc721AssetData1 = decodedAssetData.nestedAssetData[1] as ERC721AssetData; - const decodedErc20AssetData2 = decodedAssetData.nestedAssetData[2]; - // tslint:disable-next-line:no-unnecessary-type-assertion - const decodedErc721AssetData2 = decodedAssetData.nestedAssetData[3] as ERC721AssetData; + const expectedNestedAssetDataLength = 6; + expect(decodedAssetData.nestedAssetData.length).to.be.equal(expectedNestedAssetDataLength); + // validate nested asset data (outer) + let nestedAssetDataIndex = 0; + const decodedErc20AssetData1 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++]; expect(decodedErc20AssetData1.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address); expect(decodedErc20AssetData1.assetProxyId).to.equal(AssetProxyId.ERC20); + // tslint:disable-next-line:no-unnecessary-type-assertion + const decodedErc721AssetData1 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC721AssetData; expect(decodedErc721AssetData1.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address); expect(decodedErc721AssetData1.assetProxyId).to.equal(AssetProxyId.ERC721); - expect(decodedErc721AssetData1.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId); + // tslint:disable-next-line:no-unnecessary-type-assertion + const decodedErc1155AssetData1 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC1155AssetData; + expect(decodedErc1155AssetData1.tokenAddress).to.be.equal(KNOWN_ERC1155_ENCODING.tokenAddress); + expect(decodedErc1155AssetData1.tokenValues).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenValues); + expect(decodedErc1155AssetData1.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds); + expect(decodedErc1155AssetData1.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData); + // validate nested asset data (inner) + const decodedErc20AssetData2 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++]; expect(decodedErc20AssetData2.tokenAddress).to.equal(KNOWN_ERC20_ENCODING.address); expect(decodedErc20AssetData2.assetProxyId).to.equal(AssetProxyId.ERC20); + // tslint:disable-next-line:no-unnecessary-type-assertion + const decodedErc721AssetData2 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC721AssetData; expect(decodedErc721AssetData2.tokenAddress).to.equal(KNOWN_ERC721_ENCODING.address); expect(decodedErc721AssetData2.assetProxyId).to.equal(AssetProxyId.ERC721); - expect(decodedErc721AssetData2.tokenId).to.be.bignumber.equal(KNOWN_ERC721_ENCODING.tokenId); + // tslint:disable-next-line:no-unnecessary-type-assertion + const decodedErc1155AssetData2 = decodedAssetData.nestedAssetData[nestedAssetDataIndex++] as ERC1155AssetData; + expect(decodedErc1155AssetData2.tokenAddress).to.be.equal(KNOWN_ERC1155_ENCODING.tokenAddress); + expect(decodedErc1155AssetData2.tokenValues).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenValues); + expect(decodedErc1155AssetData2.tokenIds).to.be.deep.equal(KNOWN_ERC1155_ENCODING.tokenIds); + expect(decodedErc1155AssetData2.callbackData).to.be.equal(KNOWN_ERC1155_ENCODING.callbackData); }); }); From 6957e6e8f72b3a0518569c737cd8ed13eb7bce7d Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Mar 2019 16:50:09 -0800 Subject: [PATCH 04/10] ERC1155 integration tests with MultiAssetProxy --- contracts/asset-proxy/test/proxies.ts | 348 ++++++++++++++++++++++++++ contracts/exchange/test/core.ts | 2 +- contracts/test-utils/src/constants.ts | 2 +- 3 files changed, 350 insertions(+), 2 deletions(-) diff --git a/contracts/asset-proxy/test/proxies.ts b/contracts/asset-proxy/test/proxies.ts index 7977871358..638b550e4f 100644 --- a/contracts/asset-proxy/test/proxies.ts +++ b/contracts/asset-proxy/test/proxies.ts @@ -28,6 +28,7 @@ import * as chai from 'chai'; import { LogWithDecodedArgs } from 'ethereum-types'; import * as _ from 'lodash'; +import { Erc1155Wrapper } from '../../erc1155'; import { artifacts, ERC20ProxyContract, @@ -77,6 +78,15 @@ describe('Asset Transfer Proxies', () => { let erc721AFromTokenId: BigNumber; let erc721BFromTokenId: BigNumber; + let erc1155Proxy: ERC721ProxyContract; + let erc1155ProxyWrapper: ERC1155ProxyWrapper; + let erc1155Contract: ERC1155MintableContract; + let erc1155Contract2: ERC1155MintableContract; + let erc1155Wrapper: Erc1155Wrapper; + let erc1155Wrapper2: Erc1155Wrapper; + let erc1155FungibleTokens: BigNumber[]; + let erc1155NonFungibleTokensOwnedBySpender: BigNumber[]; + before(async () => { await blockchainLifecycle.startAsync(); }); @@ -127,6 +137,22 @@ describe('Asset Transfer Proxies', () => { constants.AWAIT_TRANSACTION_MINED_MS, ); + // Configure ERC115Proxy + erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner); + erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync(); + await web3Wrapper.awaitTransactionSuccessAsync( + await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // Configure MultiAssetProxy await web3Wrapper.awaitTransactionSuccessAsync( await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(authorized, { @@ -146,6 +172,12 @@ describe('Asset Transfer Proxies', () => { }), constants.AWAIT_TRANSACTION_MINED_MS, ); + await web3Wrapper.awaitTransactionSuccessAsync( + await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc1155Proxy.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); // Deploy and configure ERC20 tokens const numDummyErc20ToDeploy = 2; @@ -213,6 +245,22 @@ describe('Asset Transfer Proxies', () => { const erc721Balances = await erc721Wrapper.getBalancesAsync(); erc721AFromTokenId = erc721Balances[fromAddress][erc721TokenA.address][0]; erc721BFromTokenId = erc721Balances[fromAddress][erc721TokenB.address][0]; + + // Deploy & configure ERC1155 tokens and receiver + [erc1155Wrapper, erc1155Wrapper2] = await erc1155ProxyWrapper.deployDummyContractsAsync(); + erc1155Contract = erc1155Wrapper.getContract(); + erc1155Contract2 = erc1155Wrapper2.getContract(); + await erc1155ProxyWrapper.setBalancesAndAllowancesAsync(); + erc1155FungibleTokens = erc1155ProxyWrapper.getFungibleTokenIds(); + const nonFungibleTokens = erc1155ProxyWrapper.getNonFungibleTokenIds(); + const tokenBalances = await erc1155ProxyWrapper.getBalancesAsync(); + erc1155NonFungibleTokensOwnedBySpender = []; + _.each(nonFungibleTokens, (nonFungibleToken: BigNumber) => { + const nonFungibleTokenAsString = nonFungibleToken.toString(); + const nonFungibleTokenHeldBySpender = + tokenBalances.nonFungible[fromAddress][erc1155Contract.address][nonFungibleTokenAsString][0]; + erc1155NonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender); + }); }); beforeEach(async () => { await blockchainLifecycle.startAsync(); @@ -944,6 +992,306 @@ describe('Asset Transfer Proxies', () => { expect(newOwnerFromAsset1).to.be.equal(toAddress); expect(newOwnerFromAsset2).to.be.equal(toAddress); }); + it('should transfer a fungible ERC1155 token', async () => { + // setup test parameters + const tokenHolders = [fromAddress, toAddress]; + const tokensToTransfer = erc1155FungibleTokens.slice(0, 1); + const valuesToTransfer = [new BigNumber(25)]; + const valueMultiplier = new BigNumber(23); + const receiverCallbackData = '0x0102030405'; + // check balances before transfer + const expectedInitialBalances = [ + // from + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // to + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // encode erc1155 asset data + const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + tokensToTransfer, + valuesToTransfer, + receiverCallbackData, + ); + // encode multi-asset data + const multiAssetAmount = new BigNumber(5); + const amounts = [valueMultiplier]; + const nestedAssetData = [erc1155AssetData]; + const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + assetData, + fromAddress, + toAddress, + multiAssetAmount, + ); + // execute transfer + await web3Wrapper.awaitTransactionSuccessAsync( + await web3Wrapper.sendTransactionAsync({ + to: multiAssetProxy.address, + data, + from: authorized, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // check balances + const totalValueTransferred = valuesToTransfer[0].times(valueMultiplier).times(multiAssetAmount); + const expectedFinalBalances = [ + // from + expectedInitialBalances[0].minus(totalValueTransferred), + // to + expectedInitialBalances[1].plus(totalValueTransferred), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); + it('should successfully transfer multiple fungible tokens of the same ERC1155 contract', async () => { + // setup test parameters + const tokenHolders = [fromAddress, toAddress]; + const tokensToTransfer = erc1155FungibleTokens.slice(0, 3); + const valuesToTransfer = [new BigNumber(25), new BigNumber(35), new BigNumber(45)]; + const valueMultiplier = new BigNumber(23); + const receiverCallbackData = '0x0102030405'; + // check balances before transfer + const expectedInitialBalances = [ + // from + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // to + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // encode erc1155 asset data + const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + tokensToTransfer, + valuesToTransfer, + receiverCallbackData, + ); + // encode multi-asset data + const multiAssetAmount = new BigNumber(5); + const amounts = [valueMultiplier]; + const nestedAssetData = [erc1155AssetData]; + const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + assetData, + fromAddress, + toAddress, + multiAssetAmount, + ); + // execute transfer + await web3Wrapper.awaitTransactionSuccessAsync( + await web3Wrapper.sendTransactionAsync({ + to: multiAssetProxy.address, + data, + from: authorized, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // check balances + const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => { + return value.times(valueMultiplier).times(multiAssetAmount); + }); + const expectedFinalBalances = [ + // from + expectedInitialBalances[0].minus(totalValuesTransferred[0]), + expectedInitialBalances[1].minus(totalValuesTransferred[1]), + expectedInitialBalances[2].minus(totalValuesTransferred[2]), + // to + expectedInitialBalances[3].plus(totalValuesTransferred[0]), + expectedInitialBalances[4].plus(totalValuesTransferred[1]), + expectedInitialBalances[5].plus(totalValuesTransferred[2]), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); + it('should successfully transfer multiple fungible/non-fungible tokens of the same ERC1155 contract', async () => { + // setup test parameters + const tokenHolders = [fromAddress, toAddress]; + const fungibleTokensToTransfer = erc1155FungibleTokens.slice(0, 1); + const nonFungibleTokensToTransfer = erc1155NonFungibleTokensOwnedBySpender.slice(0, 1); + const tokensToTransfer = fungibleTokensToTransfer.concat(nonFungibleTokensToTransfer); + const valuesToTransfer = [new BigNumber(25), new BigNumber(1)]; + const valueMultiplier = new BigNumber(1); + const receiverCallbackData = '0x0102030405'; + // check balances before transfer + const nftOwnerBalance = new BigNumber(1); + const nftNotOwnerBalance = new BigNumber(0); + const expectedInitialBalances = [ + // from + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + nftOwnerBalance, + // to + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + nftNotOwnerBalance, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // encode erc1155 asset data + const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + tokensToTransfer, + valuesToTransfer, + receiverCallbackData, + ); + // encode multi-asset data + const multiAssetAmount = new BigNumber(1); + const amounts = [valueMultiplier]; + const nestedAssetData = [erc1155AssetData]; + const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + assetData, + fromAddress, + toAddress, + multiAssetAmount, + ); + // execute transfer + await web3Wrapper.awaitTransactionSuccessAsync( + await web3Wrapper.sendTransactionAsync({ + to: multiAssetProxy.address, + data, + from: authorized, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // check balances + const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => { + return value.times(valueMultiplier).times(multiAssetAmount); + }); + const expectedFinalBalances = [ + // from + expectedInitialBalances[0].minus(totalValuesTransferred[0]), + expectedInitialBalances[1].minus(totalValuesTransferred[1]), + // to + expectedInitialBalances[2].plus(totalValuesTransferred[0]), + expectedInitialBalances[3].plus(totalValuesTransferred[1]), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); + it('should successfully transfer multiple different ERC1155 tokens', async () => { + // setup test parameters + const tokenHolders = [fromAddress, toAddress]; + const tokensToTransfer = erc1155FungibleTokens.slice(0, 1); + const valuesToTransfer = [new BigNumber(25)]; + const valueMultiplier = new BigNumber(23); + const receiverCallbackData = '0x0102030405'; + // check balances before transfer + const expectedInitialBalances = [ + // from + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + // to + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // encode erc1155 asset data + const erc1155AssetData1 = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + tokensToTransfer, + valuesToTransfer, + receiverCallbackData, + ); + const erc1155AssetData2 = assetDataUtils.encodeERC1155AssetData( + erc1155Contract2.address, + tokensToTransfer, + valuesToTransfer, + receiverCallbackData, + ); + // encode multi-asset data + const multiAssetAmount = new BigNumber(5); + const amounts = [valueMultiplier, valueMultiplier]; + const nestedAssetData = [erc1155AssetData1, erc1155AssetData2]; + const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + assetData, + fromAddress, + toAddress, + multiAssetAmount, + ); + // execute transfer + await web3Wrapper.awaitTransactionSuccessAsync( + await web3Wrapper.sendTransactionAsync({ + to: multiAssetProxy.address, + data, + from: authorized, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // check balances + const totalValueTransferred = valuesToTransfer[0].times(valueMultiplier).times(multiAssetAmount); + const expectedFinalBalances = [ + // from + expectedInitialBalances[0].minus(totalValueTransferred), + // to + expectedInitialBalances[1].plus(totalValueTransferred), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); + it('should successfully transfer a combination of ERC20, ERC721, and ERC1155 tokens', async () => { + // setup test parameters + const inputAmount = new BigNumber(1); + const erc20Amount = new BigNumber(10); + const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); + const erc721Amount = new BigNumber(1); + const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); + const erc1155TokenHolders = [fromAddress, toAddress]; + const erc1155TokensToTransfer = erc1155FungibleTokens.slice(0, 1); + const erc1155ValuesToTransfer = [new BigNumber(25)]; + const erc1155Amount = new BigNumber(23); + const erc1155ReceiverCallbackData = '0x0102030405'; + const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( + erc1155Contract.address, + erc1155TokensToTransfer, + erc1155ValuesToTransfer, + erc1155ReceiverCallbackData, + ); + const amounts = [erc20Amount, erc721Amount, erc1155Amount]; + const nestedAssetData = [erc20AssetData, erc721AssetData, erc1155AssetData]; + const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); + const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( + assetData, + fromAddress, + toAddress, + inputAmount, + ); + // check balances before transfer + const erc20Balances = await erc20Wrapper.getBalancesAsync(); + const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); + expect(ownerFromAsset).to.be.equal(fromAddress); + const erc1155ExpectedInitialBalances = [ + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, + ]; + await erc1155Wrapper.assertBalancesAsync(erc1155TokenHolders, erc1155TokensToTransfer, erc1155ExpectedInitialBalances); + // execute transfer + await web3Wrapper.awaitTransactionSuccessAsync( + await web3Wrapper.sendTransactionAsync({ + to: multiAssetProxy.address, + data, + from: authorized, + gas: 1000000, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + // check balances after transfer + const newBalances = await erc20Wrapper.getBalancesAsync(); + const totalAmount = inputAmount.times(erc20Amount); + expect(newBalances[fromAddress][erc20TokenA.address]).to.be.bignumber.equal( + erc20Balances[fromAddress][erc20TokenA.address].minus(totalAmount), + ); + expect(newBalances[toAddress][erc20TokenA.address]).to.be.bignumber.equal( + erc20Balances[toAddress][erc20TokenA.address].plus(totalAmount), + ); + const newOwnerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); + expect(newOwnerFromAsset).to.be.equal(toAddress); + const erc1155TotalValueTransferred = erc1155ValuesToTransfer[0].times(erc1155Amount).times(inputAmount); + const expectedFinalBalances = [ + erc1155ExpectedInitialBalances[0].minus(erc1155TotalValueTransferred), + erc1155ExpectedInitialBalances[1].plus(erc1155TotalValueTransferred), + ]; + await erc1155Wrapper.assertBalancesAsync(erc1155TokenHolders, erc1155TokensToTransfer, expectedFinalBalances); + }); it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => { const inputAmount = new BigNumber(1); const erc20Amount = new BigNumber(10); diff --git a/contracts/exchange/test/core.ts b/contracts/exchange/test/core.ts index 53d6b1d028..21d5482de6 100644 --- a/contracts/exchange/test/core.ts +++ b/contracts/exchange/test/core.ts @@ -121,7 +121,7 @@ describe('Exchange core', () => { ); [erc721Token] = await erc721Wrapper.deployDummyTokensAsync(); erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync(); - [erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyTokensAsync(); + [erc1155Wrapper] = await erc1155ProxyWrapper.deployDummyContractsAsync(); erc1155Contract = erc1155Wrapper.getContract(); exchange = await ExchangeContract.deployFrom0xArtifactAsync( artifacts.Exchange, diff --git a/contracts/test-utils/src/constants.ts b/contracts/test-utils/src/constants.ts index 2e58d764d0..199042edc0 100644 --- a/contracts/test-utils/src/constants.ts +++ b/contracts/test-utils/src/constants.ts @@ -38,7 +38,7 @@ export const constants = { NUM_DUMMY_ERC20_TO_DEPLOY: 3, NUM_DUMMY_ERC721_TO_DEPLOY: 2, NUM_ERC721_TOKENS_TO_MINT: 2, - NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY: 1, + NUM_DUMMY_ERC1155_CONTRACTS_TO_DEPLOY: 2, NUM_ERC1155_FUNGIBLE_TOKENS_MINT: 3, NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT: 3, NULL_ADDRESS: '0x0000000000000000000000000000000000000000', From 6992bff0e0fbdd50326e190b1cd9fe5cfcfaa651 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 7 Mar 2019 17:30:16 -0800 Subject: [PATCH 05/10] Ran prettier & linter --- contracts/asset-proxy/test/proxies.ts | 46 ++++++++++++++++----------- contracts/exchange/package.json | 1 + contracts/exchange/test/core.ts | 10 +++--- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/contracts/asset-proxy/test/proxies.ts b/contracts/asset-proxy/test/proxies.ts index 638b550e4f..b4e202a9db 100644 --- a/contracts/asset-proxy/test/proxies.ts +++ b/contracts/asset-proxy/test/proxies.ts @@ -137,21 +137,21 @@ describe('Asset Transfer Proxies', () => { constants.AWAIT_TRANSACTION_MINED_MS, ); - // Configure ERC115Proxy - erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner); - erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync(); - await web3Wrapper.awaitTransactionSuccessAsync( - await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, { - from: owner, - }), - constants.AWAIT_TRANSACTION_MINED_MS, - ); - await web3Wrapper.awaitTransactionSuccessAsync( - await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, { - from: owner, - }), - constants.AWAIT_TRANSACTION_MINED_MS, - ); + // Configure ERC115Proxy + erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner); + erc1155Proxy = await erc1155ProxyWrapper.deployProxyAsync(); + await web3Wrapper.awaitTransactionSuccessAsync( + await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); + await web3Wrapper.awaitTransactionSuccessAsync( + await erc1155Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, { + from: owner, + }), + constants.AWAIT_TRANSACTION_MINED_MS, + ); // Configure MultiAssetProxy await web3Wrapper.awaitTransactionSuccessAsync( @@ -259,7 +259,7 @@ describe('Asset Transfer Proxies', () => { const nonFungibleTokenAsString = nonFungibleToken.toString(); const nonFungibleTokenHeldBySpender = tokenBalances.nonFungible[fromAddress][erc1155Contract.address][nonFungibleTokenAsString][0]; - erc1155NonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender); + erc1155NonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender); }); }); beforeEach(async () => { @@ -1240,7 +1240,7 @@ describe('Asset Transfer Proxies', () => { const erc1155ValuesToTransfer = [new BigNumber(25)]; const erc1155Amount = new BigNumber(23); const erc1155ReceiverCallbackData = '0x0102030405'; - const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( + const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( erc1155Contract.address, erc1155TokensToTransfer, erc1155ValuesToTransfer, @@ -1263,7 +1263,11 @@ describe('Asset Transfer Proxies', () => { constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, constants.INITIAL_ERC1155_FUNGIBLE_BALANCE, ]; - await erc1155Wrapper.assertBalancesAsync(erc1155TokenHolders, erc1155TokensToTransfer, erc1155ExpectedInitialBalances); + await erc1155Wrapper.assertBalancesAsync( + erc1155TokenHolders, + erc1155TokensToTransfer, + erc1155ExpectedInitialBalances, + ); // execute transfer await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.sendTransactionAsync({ @@ -1290,7 +1294,11 @@ describe('Asset Transfer Proxies', () => { erc1155ExpectedInitialBalances[0].minus(erc1155TotalValueTransferred), erc1155ExpectedInitialBalances[1].plus(erc1155TotalValueTransferred), ]; - await erc1155Wrapper.assertBalancesAsync(erc1155TokenHolders, erc1155TokensToTransfer, expectedFinalBalances); + await erc1155Wrapper.assertBalancesAsync( + erc1155TokenHolders, + erc1155TokensToTransfer, + expectedFinalBalances, + ); }); it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => { const inputAmount = new BigNumber(1); diff --git a/contracts/exchange/package.json b/contracts/exchange/package.json index 69ba190525..5f45dc25c4 100644 --- a/contracts/exchange/package.json +++ b/contracts/exchange/package.json @@ -71,6 +71,7 @@ "@0x/contracts-asset-proxy": "^1.0.9", "@0x/contracts-erc20": "^1.0.9", "@0x/contracts-erc721": "^1.0.9", + "@0x/contracts-erc1155": "^0.0.1", "@0x/contracts-exchange-libs": "^1.1.3", "@0x/contracts-utils": "^2.0.8", "@0x/order-utils": "^7.0.2", diff --git a/contracts/exchange/test/core.ts b/contracts/exchange/test/core.ts index 21d5482de6..ff6874c0ea 100644 --- a/contracts/exchange/test/core.ts +++ b/contracts/exchange/test/core.ts @@ -1,12 +1,13 @@ import { artifacts as proxyArtifacts, + ERC1155ProxyWrapper, ERC20ProxyContract, ERC20Wrapper, ERC721ProxyContract, ERC721Wrapper, MultiAssetProxyContract, - ERC1155ProxyWrapper, } from '@0x/contracts-asset-proxy'; +import { ERC1155MintableContract } from '@0x/contracts-erc1155'; import { artifacts as erc20Artifacts, DummyERC20TokenContract, @@ -27,7 +28,6 @@ import { txDefaults, web3Wrapper, } from '@0x/contracts-test-utils'; -import { ERC1155MintableContract, DummyERC1155ReceiverBatchTokenReceivedEventArgs } from '@0x/contracts-erc1155'; import { BlockchainLifecycle } from '@0x/dev-utils'; import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; @@ -38,6 +38,7 @@ import { LogWithDecodedArgs } from 'ethereum-types'; import ethUtil = require('ethereumjs-util'); import * as _ from 'lodash'; +import { Erc1155Wrapper } from '../../erc1155/lib/src'; import { artifacts, ExchangeCancelEventArgs, @@ -46,8 +47,6 @@ import { ReentrantERC20TokenContract, TestStaticCallReceiverContract, } from '../src'; -import { Erc1155Wrapper, ERC1155Contract } from '../../erc1155/lib/src'; -import { Exception } from 'handlebars'; chaiSetup.configure(); const expect = chai.expect; @@ -1087,8 +1086,7 @@ describe('Exchange core', () => { ); }); }); - - describe.only('Testing exchange of erc1155 assets', () => { + describe('Testing exchange of erc1155 assets', () => { it('should allow a single fungible erc1155 asset to be exchanged for another', async () => { // setup test parameters const tokenHolders = [makerAddress, takerAddress]; From c0260bc44acfc961475dbe60b32393b87a80ac61 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 11 Mar 2019 18:24:19 -0700 Subject: [PATCH 06/10] rebased against development --- contracts/asset-proxy/test/proxies.ts | 3 ++- contracts/exchange/package.json | 2 +- packages/order-utils/src/asset_data_utils.ts | 3 --- packages/order-utils/test/asset_data_utils_test.ts | 4 ---- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/contracts/asset-proxy/test/proxies.ts b/contracts/asset-proxy/test/proxies.ts index b4e202a9db..81d1475d82 100644 --- a/contracts/asset-proxy/test/proxies.ts +++ b/contracts/asset-proxy/test/proxies.ts @@ -1,3 +1,4 @@ +import { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155'; import { artifacts as erc20Artifacts, DummyERC20TokenContract, @@ -28,9 +29,9 @@ import * as chai from 'chai'; import { LogWithDecodedArgs } from 'ethereum-types'; import * as _ from 'lodash'; -import { Erc1155Wrapper } from '../../erc1155'; import { artifacts, + ERC1155ProxyWrapper, ERC20ProxyContract, ERC20Wrapper, ERC721ProxyContract, diff --git a/contracts/exchange/package.json b/contracts/exchange/package.json index 5f45dc25c4..c32eb31e5e 100644 --- a/contracts/exchange/package.json +++ b/contracts/exchange/package.json @@ -71,7 +71,7 @@ "@0x/contracts-asset-proxy": "^1.0.9", "@0x/contracts-erc20": "^1.0.9", "@0x/contracts-erc721": "^1.0.9", - "@0x/contracts-erc1155": "^0.0.1", + "@0x/contracts-erc1155": "^1.0.0", "@0x/contracts-exchange-libs": "^1.1.3", "@0x/contracts-utils": "^2.0.8", "@0x/order-utils": "^7.0.2", diff --git a/packages/order-utils/src/asset_data_utils.ts b/packages/order-utils/src/asset_data_utils.ts index 1dc6922365..2acf57d5f6 100644 --- a/packages/order-utils/src/asset_data_utils.ts +++ b/packages/order-utils/src/asset_data_utils.ts @@ -5,9 +5,6 @@ import { ERC1155AssetDataNoProxyId, ERC20AssetData, ERC721AssetData, - ERC1155AssetData, - ERC1155AssetDataAbi, - ERC1155AssetDataNoProxyId, MultiAssetData, MultiAssetDataWithRecursiveDecoding, SingleAssetData, diff --git a/packages/order-utils/test/asset_data_utils_test.ts b/packages/order-utils/test/asset_data_utils_test.ts index a9cdcf44f2..203956948e 100644 --- a/packages/order-utils/test/asset_data_utils_test.ts +++ b/packages/order-utils/test/asset_data_utils_test.ts @@ -68,11 +68,7 @@ describe('assetDataUtils', () => { KNOWN_ERC1155_ENCODING.tokenAddress, KNOWN_ERC1155_ENCODING.tokenIds, KNOWN_ERC1155_ENCODING.tokenValues, -<<<<<<< HEAD KNOWN_ERC1155_ENCODING.callbackData, -======= - KNOWN_ERC1155_ENCODING.callbackData ->>>>>>> 5bddc5795... ERC1155 Asset Data tests + types ); expect(assetData).to.equal(KNOWN_ERC1155_ENCODING.assetData); }); From 29ebed951499c763d0ef7755ada325b85edee3c0 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 14 Mar 2019 22:13:53 -0700 Subject: [PATCH 07/10] Added ERC1155 artifacts to log decoder for exchange wrapper --- contracts/exchange/test/utils/exchange_wrapper.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/contracts/exchange/test/utils/exchange_wrapper.ts b/contracts/exchange/test/utils/exchange_wrapper.ts index fef8b55db3..a06e35a462 100644 --- a/contracts/exchange/test/utils/exchange_wrapper.ts +++ b/contracts/exchange/test/utils/exchange_wrapper.ts @@ -1,3 +1,4 @@ +import { artifacts as erc1155Artifacts } from '@0x/contracts-erc1155'; import { artifacts as erc20Artifacts } from '@0x/contracts-erc20'; import { artifacts as erc721Artifacts } from '@0x/contracts-erc721'; import { @@ -25,7 +26,12 @@ export class ExchangeWrapper { constructor(exchangeContract: ExchangeContract, provider: Web3ProviderEngine | ZeroExProvider) { this._exchange = exchangeContract; this._web3Wrapper = new Web3Wrapper(provider); - this._logDecoder = new LogDecoder(this._web3Wrapper, { ...artifacts, ...erc20Artifacts, ...erc721Artifacts }); + this._logDecoder = new LogDecoder(this._web3Wrapper, { + ...artifacts, + ...erc20Artifacts, + ...erc721Artifacts, + ...erc1155Artifacts, + }); } public async fillOrderAsync( signedOrder: SignedOrder, From 7024f29865561f3f94f555bf56b50bc89a8f4883 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Thu, 14 Mar 2019 23:08:52 -0700 Subject: [PATCH 08/10] updated changelogs --- contracts/asset-proxy/CHANGELOG.json | 6 +++++- contracts/exchange/CHANGELOG.json | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/contracts/asset-proxy/CHANGELOG.json b/contracts/asset-proxy/CHANGELOG.json index fc665e19a1..2871872a8a 100644 --- a/contracts/asset-proxy/CHANGELOG.json +++ b/contracts/asset-proxy/CHANGELOG.json @@ -13,12 +13,16 @@ { "note": "Bumped solidity version to ^0.5.5", "pr": 1701 + }, + { + "note": "Integration testing for ERC1155Proxy", + "pr": 1673 } ] }, { "timestamp": 1551479279, - "version": "1.0.9", + "version": "1.å.9", "changes": [ { "note": "Dependencies updated" diff --git a/contracts/exchange/CHANGELOG.json b/contracts/exchange/CHANGELOG.json index f5ec62d609..6f9c055614 100644 --- a/contracts/exchange/CHANGELOG.json +++ b/contracts/exchange/CHANGELOG.json @@ -9,6 +9,10 @@ { "note": "Upgrade contracts to Solidity 0.5.5", "pr": 1682 + }, + { + "note": "Integration testing for ERC1155Proxy", + "pr": 1673 } ] }, From 30d0bdec07d9a376efe0cc77d5a21f7e4ff7b0a6 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 18 Mar 2019 17:31:47 -0700 Subject: [PATCH 09/10] Updated changelog and yarn.lock --- contracts/asset-proxy/CHANGELOG.json | 2 +- yarn.lock | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/contracts/asset-proxy/CHANGELOG.json b/contracts/asset-proxy/CHANGELOG.json index 2871872a8a..4bdbc98084 100644 --- a/contracts/asset-proxy/CHANGELOG.json +++ b/contracts/asset-proxy/CHANGELOG.json @@ -22,7 +22,7 @@ }, { "timestamp": 1551479279, - "version": "1.å.9", + "version": "1.0.9", "changes": [ { "note": "Dependencies updated" diff --git a/yarn.lock b/yarn.lock index ed2369fc1a..19f79e4574 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6498,7 +6498,6 @@ ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0, ether ethereumjs-block@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.0.tgz#8c6c3ab4a5eff0a16d9785fbeedbe643f4dbcbef" - integrity sha512-Ye+uG/L2wrp364Zihdlr/GfC3ft+zG8PdHcRtsBFNNH1CkOhxOwdB8friBU85n89uRZ9eIMAywCq0F4CwT1wAw== dependencies: async "^2.0.1" ethereumjs-common "^1.1.0" @@ -6521,7 +6520,6 @@ ethereumjs-common@^0.6.0: ethereumjs-common@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.1.0.tgz#5ec9086c314d619d8f05e79a0525829fcb0e93cb" - integrity sha512-LUmYkKV/HcZbWRyu3OU9YOevsH3VJDXtI6kEd8VZweQec+JjDGKCmAVKUyzhYUHqxRJu7JNALZ3A/b3NXOP6tA== ethereumjs-tx@1.3.7: version "1.3.7" @@ -6574,7 +6572,6 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum ethereumjs-util@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8" - integrity sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q== dependencies: bn.js "^4.11.0" create-hash "^1.1.2" @@ -6603,7 +6600,6 @@ ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4: ethereumjs-vm@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" - integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== dependencies: async "^2.1.2" async-eventemitter "^0.2.2" @@ -6671,7 +6667,6 @@ ethjs-unit@0.1.6: ethjs-util@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== dependencies: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" @@ -7543,7 +7538,6 @@ ganache-cli@6.4.1: ganache-core@^2.5.3: version "2.5.3" resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.5.3.tgz#8c6f21d820a694826082dfbb2dc59f834a6874fc" - integrity sha512-lTqPSxgWS5p4zJ8yNbhhsBXMPfcuV+jjnnYtsbJTph9L6InA6UkNpO0hhHuDFWF3GpblP3LjvWPpqW+X6pdZGg== dependencies: abstract-leveldown "3.0.0" async "2.6.1" @@ -11084,7 +11078,6 @@ merkle-patricia-tree@2.3.1, merkle-patricia-tree@^2.1.2: merkle-patricia-tree@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== dependencies: async "^1.4.2" ethereumjs-util "^5.0.0" @@ -13558,7 +13551,6 @@ react-dom@^16.3.2: react-dom@^16.4.2: version "16.8.4" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.4.tgz#1061a8e01a2b3b0c8160037441c3bf00a0e3bc48" - integrity sha512-Ob2wK7XG2tUDt7ps7LtLzGYYB6DXMCLj0G5fO6WeEICtT4/HdpOi7W/xLzZnR6RCG1tYza60nMdqtxzA8FaPJQ== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -13871,7 +13863,6 @@ react@^16.3.2: react@^16.4.2: version "16.8.4" resolved "https://registry.yarnpkg.com/react/-/react-16.8.4.tgz#fdf7bd9ae53f03a9c4cd1a371432c206be1c4768" - integrity sha512-0GQ6gFXfUH7aZcjGVymlPOASTuSjlQL4ZtVC5YKH+3JL6bBLCVO21DknzmaPlI90LN253ojj02nsapy+j7wIjg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -14752,7 +14743,6 @@ schedule@^0.5.0: scheduler@^0.13.4: version "0.13.4" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.4.tgz#8fef05e7a3580c76c0364d2df5e550e4c9140298" - integrity sha512-cvSOlRPxOHs5dAhP9yiS/6IDmVAVxmk33f0CtTJRkmUWcb1Us+t7b1wqdzoC0REw2muC9V5f1L/w5R5uKGaepA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" From 98c6fa10e65d5fa0255c7db92e19c22904f37dfd Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Mon, 18 Mar 2019 17:42:06 -0700 Subject: [PATCH 10/10] Added 1explicit ERC1555Poxy testsfor cwhen receiver allback data is NULLL (0x) --- contracts/asset-proxy/test/erc1155_proxy.ts | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/contracts/asset-proxy/test/erc1155_proxy.ts b/contracts/asset-proxy/test/erc1155_proxy.ts index 7931fdfda0..f55e11024f 100644 --- a/contracts/asset-proxy/test/erc1155_proxy.ts +++ b/contracts/asset-proxy/test/erc1155_proxy.ts @@ -433,6 +433,50 @@ describe('ERC1155Proxy', () => { ]; await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); }); + it('should successfully transfer value to a smart contract and trigger its callback, when callback `data` is NULL', async () => { + // setup test parameters + const tokenHolders = [spender, receiverContract]; + const tokensToTransfer = fungibleTokens.slice(0, 1); + const valuesToTransfer = [fungibleValueToTransferLarge]; + const valueMultiplier = valueMultiplierSmall; + const totalValuesTransferred = _.map(valuesToTransfer, (value: BigNumber) => { + return value.times(valueMultiplier); + }); + // check balances before transfer + const expectedInitialBalances = [spenderInitialFungibleBalance, receiverContractInitialFungibleBalance]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); + // execute transfer + const nullReceiverCallbackData = '0x'; + const txReceipt = await erc1155ProxyWrapper.transferFromWithLogsAsync( + spender, + receiverContract, + erc1155Contract.address, + tokensToTransfer, + valuesToTransfer, + valueMultiplier, + nullReceiverCallbackData, + authorized, + ); + // check receiver log ignored extra asset data + expect(txReceipt.logs.length).to.be.equal(2); + const receiverLog = txReceipt.logs[1] as LogWithDecodedArgs< + DummyERC1155ReceiverBatchTokenReceivedEventArgs + >; + expect(receiverLog.args.operator).to.be.equal(erc1155Proxy.address); + expect(receiverLog.args.from).to.be.equal(spender); + expect(receiverLog.args.tokenIds.length).to.be.deep.equal(1); + expect(receiverLog.args.tokenIds[0]).to.be.bignumber.equal(tokensToTransfer[0]); + expect(receiverLog.args.tokenValues.length).to.be.deep.equal(1); + expect(receiverLog.args.tokenValues[0]).to.be.bignumber.equal(totalValuesTransferred[0]); + // note - if the `extraData` is ignored then the receiver log should ignore it as well. + expect(receiverLog.args.data).to.be.deep.equal(nullReceiverCallbackData); + // check balances after transfer + const expectedFinalBalances = [ + expectedInitialBalances[0].minus(totalValuesTransferred[0]), + expectedInitialBalances[1].plus(totalValuesTransferred[0]), + ]; + await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances); + }); it('should successfully transfer value and ignore extra assetData', async () => { // setup test parameters const tokenHolders = [spender, receiverContract];