Replace assetDataUtils with DevUtilsContract wherever possible (#2304)

* Replace assetDataUtils with DevUtilsContract wherever possible

Does not replace from @0x/instant and some @0x/order-utils uses

* Add revertIfInvalidAssetData to LibAssetData

This is needed to replace `assetDataUtils.decodeAssetDataOrThrow`.
Because it's used in packages and not only contracts, we should wait
to deploy the updated contract so we can update `@0x/contract-artifacts`,
`@0x/abi-gen-wrappers`, and `@0x/contract-wrappers` first.

* remove usages of signatureUtils

* fix test for  optimised encoding

* refactor @0x/contracts-integrations

* update changelogs

* Move @0x/contracts-dev-utils from devDependencies to dependencies
It is exported as part of the package
This commit is contained in:
Xianny 2019-11-06 19:40:20 -08:00 committed by GitHub
parent ec26cff656
commit 6a852ab0ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 1408 additions and 970 deletions

View File

@ -1,4 +1,13 @@
[ [
{
"version": "2.3.0-beta.1",
"changes": [
{
"note": "ERC20Wrapper and ERC1155ProxyWrapper constructors now require an instance of DevUtilsContract",
"pr": 2034
}
]
},
{ {
"version": "2.3.0-beta.0", "version": "2.3.0-beta.0",
"changes": [ "changes": [

View File

@ -72,6 +72,7 @@
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^5.5.0-beta.0", "@0x/base-contract": "^5.5.0-beta.0",
"@0x/contracts-dev-utils": "^0.1.0-beta.0",
"@0x/contracts-erc1155": "^1.2.0-beta.0", "@0x/contracts-erc1155": "^1.2.0-beta.0",
"@0x/contracts-erc20": "^2.3.0-beta.0", "@0x/contracts-erc20": "^2.3.0-beta.0",
"@0x/contracts-erc721": "^2.2.0-beta.0", "@0x/contracts-erc721": "^2.2.0-beta.0",

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { import {
artifacts as erc1155Artifacts, artifacts as erc1155Artifacts,
DummyERC1155ReceiverBatchTokenReceivedEventArgs, DummyERC1155ReceiverBatchTokenReceivedEventArgs,
@ -15,7 +16,6 @@ import {
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId, RevertReason } from '@0x/types'; import { AssetProxyId, RevertReason } from '@0x/types';
import { BigNumber, SafeMathRevertErrors } from '@0x/utils'; import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -23,7 +23,7 @@ import { LogWithDecodedArgs } from 'ethereum-types';
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { artifacts, ERC1155ProxyContract, ERC1155ProxyWrapper } from '../src'; import { artifacts, ERC1155ProxyContract, ERC1155ProxyWrapper, IAssetDataContract } from '../src';
chaiSetup.configure(); chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
@ -59,6 +59,8 @@ describe('ERC1155Proxy', () => {
// tokens // tokens
let fungibleTokens: BigNumber[]; let fungibleTokens: BigNumber[];
let nonFungibleTokensOwnedBySpender: BigNumber[]; let nonFungibleTokensOwnedBySpender: BigNumber[];
// devUtils for encoding and decoding assetData
let devUtils: DevUtilsContract;
// tests // tests
before(async () => { before(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
@ -95,6 +97,8 @@ describe('ERC1155Proxy', () => {
tokenBalances.nonFungible[spender][erc1155Contract.address][nonFungibleTokenAsString][0]; tokenBalances.nonFungible[spender][erc1155Contract.address][nonFungibleTokenAsString][0];
nonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender); nonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender);
}); });
// set up devUtils
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider, { from: owner });
}); });
beforeEach(async () => { beforeEach(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
@ -630,7 +634,7 @@ describe('ERC1155Proxy', () => {
return value.times(valueMultiplier); return value.times(valueMultiplier);
}); });
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -732,18 +736,16 @@ describe('ERC1155Proxy', () => {
const tokensToTransfer = [new BigNumber(1), new BigNumber(2)]; const tokensToTransfer = [new BigNumber(1), new BigNumber(2)];
const valuesToTransfer = tokensToTransfer; const valuesToTransfer = tokensToTransfer;
const valueMultiplier = new BigNumber(2); const valueMultiplier = new BigNumber(2);
const assetData = assetDataUtils.encodeERC1155AssetData(
erc1155ContractAddress, // hand encode optimized assetData because our tooling (based on LibAssetData.sol/encodeERC1155AssetData) does not use optimized encoding
tokensToTransfer, const assetDataContract = new IAssetDataContract(constants.NULL_ADDRESS, provider);
valuesToTransfer, const selector = assetDataContract.ERC1155Assets.getSelector();
receiverCallbackData, const assetDataWithoutContractAddress =
);
// remove the function selector and contract address from check, as these change on each test
const offsetToTokenIds = 74;
const assetDataWithoutContractAddress = assetData.substr(offsetToTokenIds);
const expectedAssetDataWithoutContractAddress =
'0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000'; '0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000';
expect(assetDataWithoutContractAddress).to.be.equal(expectedAssetDataWithoutContractAddress); const assetData = `${selector}000000000000000000000000${erc1155ContractAddress.substr(
2,
)}${assetDataWithoutContractAddress}`;
///// Step 4/5 ///// ///// Step 4/5 /////
// Transfer token IDs [1, 2] and amounts [1, 2] with a multiplier of 2; // Transfer token IDs [1, 2] and amounts [1, 2] with a multiplier of 2;
// the expected trade will be token IDs [1, 2] and amounts [2, 4] // the expected trade will be token IDs [1, 2] and amounts [2, 4]
@ -845,7 +847,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [new BigNumber(2), new BigNumber(2)]; const valuesToTransfer = [new BigNumber(2), new BigNumber(2)];
const valueMultiplier = new BigNumber(2); const valueMultiplier = new BigNumber(2);
// create callback data that is the encoded version of `valuesToTransfer` // create callback data that is the encoded version of `valuesToTransfer`
const generatedAssetData = assetDataUtils.encodeERC1155AssetData( const generatedAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -967,7 +969,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [new BigNumber(1), new BigNumber(2)]; const valuesToTransfer = [new BigNumber(1), new BigNumber(2)];
const valueMultiplier = new BigNumber(2); const valueMultiplier = new BigNumber(2);
// create callback data that is the encoded version of `valuesToTransfer` // create callback data that is the encoded version of `valuesToTransfer`
const generatedAssetData = assetDataUtils.encodeERC1155AssetData( const generatedAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1030,7 +1032,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1077,7 +1079,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1128,7 +1130,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1179,7 +1181,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1230,7 +1232,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1282,7 +1284,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1329,7 +1331,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1380,7 +1382,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1427,7 +1429,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1478,13 +1480,13 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
receiverCallbackData, receiverCallbackData,
); );
const txData = erc1155ProxyWrapper.getTransferFromAbiEncodedTxData( const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
spender, spender,
receiverContract, receiverContract,
erc1155Contract.address, erc1155Contract.address,
@ -1509,13 +1511,13 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge]; const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall; const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address; const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155ContractAddress, erc1155ContractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
receiverCallbackData, receiverCallbackData,
); );
const txData = erc1155ProxyWrapper.getTransferFromAbiEncodedTxData( const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
spender, spender,
receiverContract, receiverContract,
erc1155Contract.address, erc1155Contract.address,

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155'; import { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import { import {
artifacts as erc20Artifacts, artifacts as erc20Artifacts,
@ -22,7 +23,6 @@ import {
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId, RevertReason } from '@0x/types'; import { AssetProxyId, RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -56,6 +56,7 @@ describe('Asset Transfer Proxies', () => {
let fromAddress: string; let fromAddress: string;
let toAddress: string; let toAddress: string;
let devUtils: DevUtilsContract;
let erc20TokenA: DummyERC20TokenContract; let erc20TokenA: DummyERC20TokenContract;
let erc20TokenB: DummyERC20TokenContract; let erc20TokenB: DummyERC20TokenContract;
let erc721TokenA: DummyERC721TokenContract; let erc721TokenA: DummyERC721TokenContract;
@ -91,6 +92,7 @@ describe('Asset Transfer Proxies', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, notAuthorized, authorized, fromAddress, toAddress] = _.slice(accounts, 0, 5)); const usedAddresses = ([owner, notAuthorized, authorized, fromAddress, toAddress] = _.slice(accounts, 0, 5));
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner); erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
@ -230,7 +232,7 @@ describe('Asset Transfer Proxies', () => {
describe('transferFrom', () => { describe('transferFrom', () => {
it('should successfully transfer tokens', async () => { it('should successfully transfer tokens', async () => {
// Construct ERC20 asset data // Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress // Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync(); const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10); const amount = new BigNumber(10);
@ -260,7 +262,7 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens that do not return a value', async () => { it('should successfully transfer tokens that do not return a value', async () => {
// Construct ERC20 asset data // Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(noReturnErc20Token.address);
// Perform a transfer from fromAddress to toAddress // Perform a transfer from fromAddress to toAddress
const initialFromBalance = await noReturnErc20Token.balanceOf.callAsync(fromAddress); const initialFromBalance = await noReturnErc20Token.balanceOf.callAsync(fromAddress);
const initialToBalance = await noReturnErc20Token.balanceOf.callAsync(toAddress); const initialToBalance = await noReturnErc20Token.balanceOf.callAsync(toAddress);
@ -289,7 +291,9 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens and ignore extra assetData', async () => { it('should successfully transfer tokens and ignore extra assetData', async () => {
// Construct ERC20 asset data // Construct ERC20 asset data
const extraData = '0102030405060708'; const extraData = '0102030405060708';
const encodedAssetData = `${assetDataUtils.encodeERC20AssetData(erc20TokenA.address)}${extraData}`; const encodedAssetData = `${await devUtils.encodeERC20AssetData.callAsync(
erc20TokenA.address,
)}${extraData}`;
// Perform a transfer from fromAddress to toAddress // Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync(); const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10); const amount = new BigNumber(10);
@ -319,7 +323,7 @@ describe('Asset Transfer Proxies', () => {
it('should do nothing if transferring 0 amount of a token', async () => { it('should do nothing if transferring 0 amount of a token', async () => {
// Construct ERC20 asset data // Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress // Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync(); const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0); const amount = new BigNumber(0);
@ -349,7 +353,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low', async () => { it('should revert if allowances are too low', async () => {
// Construct ERC20 asset data // Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
// Create allowance less than transfer amount. Set allowance on proxy. // Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0); const allowance = new BigNumber(0);
const amount = new BigNumber(10); const amount = new BigNumber(10);
@ -378,7 +382,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low and token does not return a value', async () => { it('should revert if allowances are too low and token does not return a value', async () => {
// Construct ERC20 asset data // Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(noReturnErc20Token.address);
// Create allowance less than transfer amount. Set allowance on proxy. // Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0); const allowance = new BigNumber(0);
const amount = new BigNumber(10); const amount = new BigNumber(10);
@ -410,7 +414,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => { it('should revert if caller is not authorized', async () => {
// Construct ERC20 asset data // Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress // Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(10); const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
@ -434,7 +438,9 @@ describe('Asset Transfer Proxies', () => {
it('should revert if token returns more than 32 bytes', async () => { it('should revert if token returns more than 32 bytes', async () => {
// Construct ERC20 asset data // Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(multipleReturnErc20Token.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(
multipleReturnErc20Token.address,
);
const amount = new BigNumber(10); const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData, encodedAssetData,
@ -481,7 +487,10 @@ describe('Asset Transfer Proxies', () => {
describe('transferFrom', () => { describe('transferFrom', () => {
it('should successfully transfer tokens', async () => { it('should successfully transfer tokens', async () => {
// Construct ERC721 asset data // Construct ERC721 asset data
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const encodedAssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
// Verify pre-condition // Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(ownerFromAsset).to.be.equal(fromAddress); expect(ownerFromAsset).to.be.equal(fromAddress);
@ -509,7 +518,7 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens and ignore extra assetData', async () => { it('should successfully transfer tokens and ignore extra assetData', async () => {
// Construct ERC721 asset data // Construct ERC721 asset data
const extraData = '0102030405060708'; const extraData = '0102030405060708';
const encodedAssetData = `${assetDataUtils.encodeERC721AssetData( const encodedAssetData = `${await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address, erc721TokenA.address,
erc721AFromTokenId, erc721AFromTokenId,
)}${extraData}`; )}${extraData}`;
@ -539,7 +548,10 @@ describe('Asset Transfer Proxies', () => {
it('should not call onERC721Received when transferring to a smart contract', async () => { it('should not call onERC721Received when transferring to a smart contract', async () => {
// Construct ERC721 asset data // Construct ERC721 asset data
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const encodedAssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
// Verify pre-condition // Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(ownerFromAsset).to.be.equal(fromAddress); expect(ownerFromAsset).to.be.equal(fromAddress);
@ -569,7 +581,10 @@ describe('Asset Transfer Proxies', () => {
it('should revert if transferring 0 amount of a token', async () => { it('should revert if transferring 0 amount of a token', async () => {
// Construct ERC721 asset data // Construct ERC721 asset data
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const encodedAssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
// Verify pre-condition // Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(ownerFromAsset).to.be.equal(fromAddress); expect(ownerFromAsset).to.be.equal(fromAddress);
@ -595,7 +610,10 @@ describe('Asset Transfer Proxies', () => {
it('should revert if transferring > 1 amount of a token', async () => { it('should revert if transferring > 1 amount of a token', async () => {
// Construct ERC721 asset data // Construct ERC721 asset data
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const encodedAssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
// Verify pre-condition // Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(ownerFromAsset).to.be.equal(fromAddress); expect(ownerFromAsset).to.be.equal(fromAddress);
@ -621,7 +639,10 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low', async () => { it('should revert if allowances are too low', async () => {
// Construct ERC721 asset data // Construct ERC721 asset data
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const encodedAssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
// Verify pre-condition // Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(ownerFromAsset).to.be.equal(fromAddress); expect(ownerFromAsset).to.be.equal(fromAddress);
@ -655,7 +676,10 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => { it('should revert if caller is not authorized', async () => {
// Construct ERC721 asset data // Construct ERC721 asset data
const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const encodedAssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
// Verify pre-condition // Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId); const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
expect(ownerFromAsset).to.be.equal(fromAddress); expect(ownerFromAsset).to.be.equal(fromAddress);
@ -702,10 +726,10 @@ describe('Asset Transfer Proxies', () => {
it('should transfer a single ERC20 token', async () => { it('should transfer a single ERC20 token', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const amounts = [erc20Amount]; const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData]; const nestedAssetData = [erc20AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -733,7 +757,7 @@ describe('Asset Transfer Proxies', () => {
it('should dispatch an ERC20 transfer when input amount is 0', async () => { it('should dispatch an ERC20 transfer when input amount is 0', async () => {
const inputAmount = constants.ZERO_AMOUNT; const inputAmount = constants.ZERO_AMOUNT;
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const amounts = [erc20Amount]; const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData]; const nestedAssetData = [erc20AssetData];
const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData); const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
@ -764,11 +788,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10); const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20); const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData1 = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData2 = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const amounts = [erc20Amount1, erc20Amount2]; const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2]; const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -797,11 +821,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10); const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20); const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData1 = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20TokenB.address); const erc20AssetData2 = await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address);
const amounts = [erc20Amount1, erc20Amount2]; const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2]; const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -836,10 +860,13 @@ describe('Asset Transfer Proxies', () => {
it('should transfer a single ERC721 token', async () => { it('should transfer a single ERC721 token', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc721Amount]; const amounts = [erc721Amount];
const nestedAssetData = [erc721AssetData]; const nestedAssetData = [erc721AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -862,8 +889,11 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer multiple of the same ERC721 token', async () => { it('should successfully transfer multiple of the same ERC721 token', async () => {
const erc721Balances = await erc721Wrapper.getBalancesAsync(); const erc721Balances = await erc721Wrapper.getBalancesAsync();
const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1]; const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
const erc721AssetData1 = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData1 = await devUtils.encodeERC721AssetData.callAsync(
const erc721AssetData2 = assetDataUtils.encodeERC721AssetData( erc721TokenA.address,
erc721AFromTokenId,
);
const erc721AssetData2 = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address, erc721TokenA.address,
erc721AFromTokenId2, erc721AFromTokenId2,
); );
@ -871,7 +901,7 @@ describe('Asset Transfer Proxies', () => {
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const amounts = [erc721Amount, erc721Amount]; const amounts = [erc721Amount, erc721Amount];
const nestedAssetData = [erc721AssetData1, erc721AssetData2]; const nestedAssetData = [erc721AssetData1, erc721AssetData2];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -897,13 +927,19 @@ describe('Asset Transfer Proxies', () => {
expect(newOwnerFromAsset2).to.be.equal(toAddress); expect(newOwnerFromAsset2).to.be.equal(toAddress);
}); });
it('should successfully transfer multiple different ERC721 tokens', async () => { it('should successfully transfer multiple different ERC721 tokens', async () => {
const erc721AssetData1 = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData1 = await devUtils.encodeERC721AssetData.callAsync(
const erc721AssetData2 = assetDataUtils.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId); erc721TokenA.address,
erc721AFromTokenId,
);
const erc721AssetData2 = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenB.address,
erc721BFromTokenId,
);
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const amounts = [erc721Amount, erc721Amount]; const amounts = [erc721Amount, erc721Amount];
const nestedAssetData = [erc721AssetData1, erc721AssetData2]; const nestedAssetData = [erc721AssetData1, erc721AssetData2];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -944,7 +980,7 @@ describe('Asset Transfer Proxies', () => {
]; ];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data // encode erc1155 asset data
const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( const erc1155AssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -954,7 +990,7 @@ describe('Asset Transfer Proxies', () => {
const multiAssetAmount = new BigNumber(5); const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier]; const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData]; const nestedAssetData = [erc1155AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1000,7 +1036,7 @@ describe('Asset Transfer Proxies', () => {
]; ];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data // encode erc1155 asset data
const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( const erc1155AssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1010,7 +1046,7 @@ describe('Asset Transfer Proxies', () => {
const multiAssetAmount = new BigNumber(5); const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier]; const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData]; const nestedAssetData = [erc1155AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1064,7 +1100,7 @@ describe('Asset Transfer Proxies', () => {
]; ];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data // encode erc1155 asset data
const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( const erc1155AssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1074,7 +1110,7 @@ describe('Asset Transfer Proxies', () => {
const multiAssetAmount = new BigNumber(1); const multiAssetAmount = new BigNumber(1);
const amounts = [valueMultiplier]; const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData]; const nestedAssetData = [erc1155AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1121,13 +1157,13 @@ describe('Asset Transfer Proxies', () => {
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances); await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data // encode erc1155 asset data
const erc1155AssetData1 = assetDataUtils.encodeERC1155AssetData( const erc1155AssetData1 = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
receiverCallbackData, receiverCallbackData,
); );
const erc1155AssetData2 = assetDataUtils.encodeERC1155AssetData( const erc1155AssetData2 = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract2.address, erc1155Contract2.address,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -1137,7 +1173,7 @@ describe('Asset Transfer Proxies', () => {
const multiAssetAmount = new BigNumber(5); const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier, valueMultiplier]; const amounts = [valueMultiplier, valueMultiplier];
const nestedAssetData = [erc1155AssetData1, erc1155AssetData2]; const nestedAssetData = [erc1155AssetData1, erc1155AssetData2];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1168,15 +1204,18 @@ describe('Asset Transfer Proxies', () => {
// setup test parameters // setup test parameters
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const erc1155TokenHolders = [fromAddress, toAddress]; const erc1155TokenHolders = [fromAddress, toAddress];
const erc1155TokensToTransfer = erc1155FungibleTokens.slice(0, 1); const erc1155TokensToTransfer = erc1155FungibleTokens.slice(0, 1);
const erc1155ValuesToTransfer = [new BigNumber(25)]; const erc1155ValuesToTransfer = [new BigNumber(25)];
const erc1155Amount = new BigNumber(23); const erc1155Amount = new BigNumber(23);
const erc1155ReceiverCallbackData = '0x0102030405'; const erc1155ReceiverCallbackData = '0x0102030405';
const erc1155AssetData = assetDataUtils.encodeERC1155AssetData( const erc1155AssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
erc1155TokensToTransfer, erc1155TokensToTransfer,
erc1155ValuesToTransfer, erc1155ValuesToTransfer,
@ -1184,7 +1223,7 @@ describe('Asset Transfer Proxies', () => {
); );
const amounts = [erc20Amount, erc721Amount, erc1155Amount]; const amounts = [erc20Amount, erc721Amount, erc1155Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData, erc1155AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData, erc1155AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1239,12 +1278,15 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => { it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1276,13 +1318,19 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens and ignore extra assetData', async () => { it('should successfully transfer tokens and ignore extra assetData', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
const extraData = '0102030405060708090001020304050607080900010203040506070809000102'; const extraData = '0102030405060708090001020304050607080900010203040506070809000102';
const assetData = `${assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData)}${extraData}`; const assetData = `${await devUtils.encodeMultiAssetData.callAsync(
amounts,
nestedAssetData,
)}${extraData}`;
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1315,11 +1363,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(100); const inputAmount = new BigNumber(100);
const erc20Amount1 = new BigNumber(10); const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20); const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData1 = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20TokenB.address); const erc20AssetData2 = await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address);
const amounts = [erc20Amount1, erc20Amount2]; const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2]; const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1355,19 +1403,25 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10); const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20); const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData1 = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20TokenB.address); const erc20AssetData2 = await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721Balances = await erc721Wrapper.getBalancesAsync(); const erc721Balances = await erc721Wrapper.getBalancesAsync();
const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1]; const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
const erc721BFromTokenId2 = erc721Balances[fromAddress][erc721TokenB.address][1]; const erc721BFromTokenId2 = erc721Balances[fromAddress][erc721TokenB.address][1];
const erc721AssetData1 = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData1 = await devUtils.encodeERC721AssetData.callAsync(
const erc721AssetData2 = assetDataUtils.encodeERC721AssetData( erc721TokenA.address,
erc721AFromTokenId,
);
const erc721AssetData2 = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address, erc721TokenA.address,
erc721AFromTokenId2, erc721AFromTokenId2,
); );
const erc721AssetData3 = assetDataUtils.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId); const erc721AssetData3 = await devUtils.encodeERC721AssetData.callAsync(
const erc721AssetData4 = assetDataUtils.encodeERC721AssetData( erc721TokenB.address,
erc721BFromTokenId,
);
const erc721AssetData4 = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenB.address, erc721TokenB.address,
erc721BFromTokenId2, erc721BFromTokenId2,
); );
@ -1380,7 +1434,7 @@ describe('Asset Transfer Proxies', () => {
erc721AssetData3, erc721AssetData3,
erc721AssetData4, erc721AssetData4,
]; ];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1432,13 +1486,16 @@ describe('Asset Transfer Proxies', () => {
it('should revert if a single transfer fails', async () => { it('should revert if a single transfer fails', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
// 2 is an invalid erc721 amount // 2 is an invalid erc721 amount
const erc721Amount = new BigNumber(2); const erc721Amount = new BigNumber(2);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1457,15 +1514,17 @@ describe('Asset Transfer Proxies', () => {
it('should revert if an AssetProxy is not registered', async () => { it('should revert if an AssetProxy is not registered', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const invalidProxyId = '0x12345678'; const invalidProxyId = '0x12345678';
const invalidErc721AssetData = `${invalidProxyId}${erc721AssetData.slice(10)}`; const invalidErc721AssetData = `${invalidProxyId}${erc721AssetData.slice(10)}`;
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, invalidErc721AssetData]; const nestedAssetData = [erc20AssetData, invalidErc721AssetData];
// HACK: This is used to get around validation built into assetDataUtils const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1484,12 +1543,14 @@ describe('Asset Transfer Proxies', () => {
it('should revert if the length of `amounts` does not match the length of `nestedAssetData`', async () => { it('should revert if the length of `amounts` does not match the length of `nestedAssetData`', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc20Amount]; const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
// HACK: This is used to get around validation built into assetDataUtils const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1508,10 +1569,10 @@ describe('Asset Transfer Proxies', () => {
it('should revert if amounts multiplication results in an overflow', async () => { it('should revert if amounts multiplication results in an overflow', async () => {
const inputAmount = new BigNumber(2).pow(128); const inputAmount = new BigNumber(2).pow(128);
const erc20Amount = new BigNumber(2).pow(128); const erc20Amount = new BigNumber(2).pow(128);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const amounts = [erc20Amount]; const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData]; const nestedAssetData = [erc20AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1530,13 +1591,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if an element of `nestedAssetData` is < 4 bytes long', async () => { it('should revert if an element of `nestedAssetData` is < 4 bytes long', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = '0x123456'; const erc721AssetData = '0x123456';
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
// HACK: This is used to get around validation built into assetDataUtils const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1555,12 +1615,15 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => { it('should revert if caller is not authorized', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1579,12 +1642,15 @@ describe('Asset Transfer Proxies', () => {
it('should revert if asset data overflows beyond the bounds of calldata', async () => { it('should revert if asset data overflows beyond the bounds of calldata', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1609,12 +1675,15 @@ describe('Asset Transfer Proxies', () => {
it('should revert if asset data resolves to a location beyond the bounds of calldata', async () => { it('should revert if asset data resolves to a location beyond the bounds of calldata', async () => {
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
assetData, assetData,
fromAddress, fromAddress,
@ -1640,12 +1709,15 @@ describe('Asset Transfer Proxies', () => {
// setup test parameters // setup test parameters
const inputAmount = new BigNumber(1); const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10); const erc20Amount = new BigNumber(10);
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const erc721Amount = new BigNumber(1); const erc721Amount = new BigNumber(1);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId); const erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721TokenA.address,
erc721AFromTokenId,
);
const amounts = [erc20Amount, erc721Amount]; const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData]; const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = assetDataUtils.encodeMultiAssetData(amounts, nestedAssetData); const assetData = await devUtils.encodeMultiAssetData.callAsync(amounts, nestedAssetData);
const extraData = '01'; const extraData = '01';
const assetDataWithExtraData = `${assetData}${extraData}`; const assetDataWithExtraData = `${assetData}${extraData}`;
const badData = assetProxyInterface.transferFrom.getABIEncodedTransactionData( const badData = assetProxyInterface.transferFrom.getABIEncodedTransactionData(

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { import {
chaiSetup, chaiSetup,
constants, constants,
@ -8,7 +9,6 @@ import {
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId, RevertReason } from '@0x/types'; import { AssetProxyId, RevertReason } from '@0x/types';
import { AbiEncoder, BigNumber } from '@0x/utils'; import { AbiEncoder, BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -25,6 +25,7 @@ describe('StaticCallProxy', () => {
let fromAddress: string; let fromAddress: string;
let toAddress: string; let toAddress: string;
let devUtils: DevUtilsContract;
let staticCallProxy: IAssetProxyContract; let staticCallProxy: IAssetProxyContract;
let staticCallTarget: TestStaticCallTargetContract; let staticCallTarget: TestStaticCallTargetContract;
@ -43,6 +44,7 @@ describe('StaticCallProxy', () => {
txDefaults, txDefaults,
artifacts, artifacts,
); );
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
staticCallProxy = new IAssetProxyContract( staticCallProxy = new IAssetProxyContract(
staticCallProxyWithoutTransferFrom.address, staticCallProxyWithoutTransferFrom.address,
provider, provider,
@ -86,7 +88,7 @@ describe('StaticCallProxy', () => {
it('should revert if assetData lies outside the bounds of calldata', async () => { it('should revert if assetData lies outside the bounds of calldata', async () => {
const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData(); const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL; const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -114,9 +116,11 @@ describe('StaticCallProxy', () => {
it('should revert if the length of assetData is less than 100 bytes', async () => { it('should revert if the length of assetData is less than 100 bytes', async () => {
const staticCallData = constants.NULL_BYTES; const staticCallData = constants.NULL_BYTES;
const expectedResultHash = constants.KECCAK256_NULL; const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils const assetData = (await devUtils.encodeStaticCallAssetData.callAsync(
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash) staticCallTarget.address,
.slice(0, -128); staticCallData,
expectedResultHash,
)).slice(0, -128);
const assetDataByteLen = (assetData.length - 2) / 2; const assetDataByteLen = (assetData.length - 2) / 2;
expect((assetDataByteLen - 4) % 32).to.equal(0); expect((assetDataByteLen - 4) % 32).to.equal(0);
await expectTransactionFailedWithoutReasonAsync( await expectTransactionFailedWithoutReasonAsync(
@ -126,7 +130,7 @@ describe('StaticCallProxy', () => {
it('should revert if the offset to `staticCallData` points to outside of assetData', async () => { it('should revert if the offset to `staticCallData` points to outside of assetData', async () => {
const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData(); const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL; const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -147,7 +151,7 @@ describe('StaticCallProxy', () => {
it('should revert if the callTarget attempts to write to state', async () => { it('should revert if the callTarget attempts to write to state', async () => {
const staticCallData = staticCallTarget.updateState.getABIEncodedTransactionData(); const staticCallData = staticCallTarget.updateState.getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL; const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -159,7 +163,7 @@ describe('StaticCallProxy', () => {
it('should revert with data provided by the callTarget if the staticcall reverts', async () => { it('should revert with data provided by the callTarget if the staticcall reverts', async () => {
const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1)); const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
const expectedResultHash = constants.KECCAK256_NULL; const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -173,7 +177,7 @@ describe('StaticCallProxy', () => {
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0)); const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0));
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001'); const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer)); const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -186,7 +190,7 @@ describe('StaticCallProxy', () => {
it('should be successful if a function call with no inputs and no outputs is successful', async () => { it('should be successful if a function call with no inputs and no outputs is successful', async () => {
const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData(); const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL; const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -196,14 +200,18 @@ describe('StaticCallProxy', () => {
it('should be successful if the staticCallTarget is not a contract and no return value is expected', async () => { it('should be successful if the staticCallTarget is not a contract and no return value is expected', async () => {
const staticCallData = '0x0102030405060708'; const staticCallData = '0x0102030405060708';
const expectedResultHash = constants.KECCAK256_NULL; const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData(toAddress, staticCallData, expectedResultHash); const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
toAddress,
staticCallData,
expectedResultHash,
);
await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount); await staticCallProxy.transferFrom.awaitTransactionSuccessAsync(assetData, fromAddress, toAddress, amount);
}); });
it('should be successful if a function call with one static input returns the correct value', async () => { it('should be successful if a function call with one static input returns the correct value', async () => {
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1)); const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1));
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001'); const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer)); const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -214,7 +222,7 @@ describe('StaticCallProxy', () => {
const dynamicInput = '0x0102030405060708'; const dynamicInput = '0x0102030405060708';
const staticCallData = staticCallTarget.dynamicInputFunction.getABIEncodedTransactionData(dynamicInput); const staticCallData = staticCallTarget.dynamicInputFunction.getABIEncodedTransactionData(dynamicInput);
const expectedResultHash = constants.KECCAK256_NULL; const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -237,7 +245,7 @@ describe('StaticCallProxy', () => {
const expectedResultHash = ethUtil.bufferToHex( const expectedResultHash = ethUtil.bufferToHex(
ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)), ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
); );
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155'; import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import { import {
constants, constants,
@ -7,7 +8,6 @@ import {
LogDecoder, LogDecoder,
txDefaults, txDefaults,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -26,6 +26,7 @@ export class ERC1155ProxyWrapper {
private readonly _logDecoder: LogDecoder; private readonly _logDecoder: LogDecoder;
private readonly _dummyTokenWrappers: Erc1155Wrapper[]; private readonly _dummyTokenWrappers: Erc1155Wrapper[];
private readonly _assetProxyInterface: IAssetProxyContract; private readonly _assetProxyInterface: IAssetProxyContract;
private readonly _devUtils: DevUtilsContract;
private _proxyContract?: ERC1155ProxyContract; private _proxyContract?: ERC1155ProxyContract;
private _proxyIdIfExists?: string; private _proxyIdIfExists?: string;
private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} }; private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
@ -37,6 +38,7 @@ export class ERC1155ProxyWrapper {
this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts); this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
this._dummyTokenWrappers = []; this._dummyTokenWrappers = [];
this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider); this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
this._tokenOwnerAddresses = tokenOwnerAddresses; this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress; this._contractOwnerAddress = contractOwnerAddress;
this._fungibleTokenIds = []; this._fungibleTokenIds = [];
@ -95,7 +97,7 @@ export class ERC1155ProxyWrapper {
* @param extraData extra data to append to `transferFrom` transaction. Optional. * @param extraData extra data to append to `transferFrom` transaction. Optional.
* @return abi encoded tx data. * @return abi encoded tx data.
*/ */
public getTransferFromAbiEncodedTxData( public async getTransferFromAbiEncodedTxDataAsync(
from: string, from: string,
to: string, to: string,
contractAddress: string, contractAddress: string,
@ -105,11 +107,11 @@ export class ERC1155ProxyWrapper {
receiverCallbackData: string, receiverCallbackData: string,
authorizedSender: string, authorizedSender: string,
assetData_?: string, assetData_?: string,
): string { ): Promise<string> {
this._validateProxyContractExistsOrThrow(); this._validateProxyContractExistsOrThrow();
const assetData = const assetData =
assetData_ === undefined assetData_ === undefined
? assetDataUtils.encodeERC1155AssetData( ? await this._devUtils.encodeERC1155AssetData.callAsync(
contractAddress, contractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,
@ -169,7 +171,7 @@ export class ERC1155ProxyWrapper {
this._validateProxyContractExistsOrThrow(); this._validateProxyContractExistsOrThrow();
const assetData = const assetData =
assetData_ === undefined assetData_ === undefined
? assetDataUtils.encodeERC1155AssetData( ? await this._devUtils.encodeERC1155AssetData.callAsync(
contractAddress, contractAddress,
tokensToTransfer, tokensToTransfer,
valuesToTransfer, valuesToTransfer,

View File

@ -1,6 +1,6 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20'; import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils'; import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { ZeroExProvider } from 'ethereum-types'; import { ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -12,6 +12,7 @@ export class ERC20Wrapper {
private readonly _contractOwnerAddress: string; private readonly _contractOwnerAddress: string;
private readonly _provider: ZeroExProvider; private readonly _provider: ZeroExProvider;
private readonly _dummyTokenContracts: DummyERC20TokenContract[]; private readonly _dummyTokenContracts: DummyERC20TokenContract[];
private readonly _devUtils: DevUtilsContract;
private _proxyContract?: ERC20ProxyContract; private _proxyContract?: ERC20ProxyContract;
private _proxyIdIfExists?: string; private _proxyIdIfExists?: string;
/** /**
@ -26,6 +27,7 @@ export class ERC20Wrapper {
this._provider = provider; this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses; this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress; this._contractOwnerAddress = contractOwnerAddress;
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
} }
public async deployDummyTokensAsync( public async deployDummyTokensAsync(
numberToDeploy: number, numberToDeploy: number,
@ -80,24 +82,27 @@ export class ERC20Wrapper {
} }
} }
public async getBalanceAsync(userAddress: string, assetData: string): Promise<BigNumber> { public async getBalanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const tokenContract = this._getTokenContractFromAssetData(assetData); const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
const balance = new BigNumber(await tokenContract.balanceOf.callAsync(userAddress)); const balance = new BigNumber(await tokenContract.balanceOf.callAsync(userAddress));
return balance; return balance;
} }
public async setBalanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> { public async setBalanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(assetData); const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
await tokenContract.setBalance.awaitTransactionSuccessAsync(userAddress, amount, { await tokenContract.setBalance.awaitTransactionSuccessAsync(
from: this._contractOwnerAddress, userAddress,
}); amount,
{ from: this._contractOwnerAddress },
{ pollingIntervalMs: constants.AWAIT_TRANSACTION_MINED_MS },
);
} }
public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise<BigNumber> { public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const tokenContract = this._getTokenContractFromAssetData(assetData); const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
const proxyAddress = (this._proxyContract as ERC20ProxyContract).address; const proxyAddress = (this._proxyContract as ERC20ProxyContract).address;
const allowance = new BigNumber(await tokenContract.allowance.callAsync(userAddress, proxyAddress)); const allowance = new BigNumber(await tokenContract.allowance.callAsync(userAddress, proxyAddress));
return allowance; return allowance;
} }
public async setAllowanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> { public async setAllowanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(assetData); const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
const proxyAddress = (this._proxyContract as ERC20ProxyContract).address; const proxyAddress = (this._proxyContract as ERC20ProxyContract).address;
await tokenContract.approve.awaitTransactionSuccessAsync(proxyAddress, amount, { from: userAddress }); await tokenContract.approve.awaitTransactionSuccessAsync(proxyAddress, amount, { from: userAddress });
} }
@ -141,9 +146,8 @@ export class ERC20Wrapper {
const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address); const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address);
return tokenAddresses; return tokenAddresses;
} }
private _getTokenContractFromAssetData(assetData: string): DummyERC20TokenContract { private async _getTokenContractFromAssetDataAsync(assetData: string): Promise<DummyERC20TokenContract> {
const erc20ProxyData = assetDataUtils.decodeERC20AssetData(assetData); const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData.callAsync(assetData); // tslint:disable-line:no-unused-variable
const tokenAddress = erc20ProxyData.tokenAddress;
const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress); const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
if (tokenContractIfExists === undefined) { if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`); throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`);

View File

@ -49,6 +49,11 @@
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^4.3.0-beta.0", "@0x/abi-gen": "^4.3.0-beta.0",
"@0x/contracts-asset-proxy": "^2.3.0-beta.0",
"@0x/contracts-dev-utils": "^0.1.0-beta.0",
"@0x/contracts-erc20": "^2.3.0-beta.0",
"@0x/contracts-exchange": "^2.2.0-beta.0",
"@0x/order-utils": "^8.5.0-beta.0",
"@0x/contracts-gen": "^1.1.0-beta.0", "@0x/contracts-gen": "^1.1.0-beta.0",
"@0x/contracts-test-utils": "^3.2.0-beta.0", "@0x/contracts-test-utils": "^3.2.0-beta.0",
"@0x/dev-utils": "^2.4.0-beta.0", "@0x/dev-utils": "^2.4.0-beta.0",
@ -61,6 +66,7 @@
"chai-as-promised": "^7.1.0", "chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0", "chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1", "dirty-chai": "^2.0.1",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0", "make-promises-safe": "^1.1.0",
"mocha": "^6.2.0", "mocha": "^6.2.0",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
@ -72,19 +78,12 @@
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^5.5.0-beta.0", "@0x/base-contract": "^5.5.0-beta.0",
"@0x/contracts-asset-proxy": "^2.3.0-beta.0",
"@0x/contracts-erc20": "^2.3.0-beta.0",
"@0x/contracts-exchange": "^2.2.0-beta.0",
"@0x/contracts-exchange-libs": "^3.1.0-beta.0",
"@0x/contracts-utils": "^3.3.0-beta.0",
"@0x/order-utils": "^8.5.0-beta.0",
"@0x/types": "^2.5.0-beta.0", "@0x/types": "^2.5.0-beta.0",
"@0x/typescript-typings": "^4.4.0-beta.0", "@0x/typescript-typings": "^4.4.0-beta.0",
"@0x/utils": "^4.6.0-beta.0", "@0x/utils": "^4.6.0-beta.0",
"@0x/web3-wrapper": "^6.1.0-beta.0", "@0x/web3-wrapper": "^6.1.0-beta.0",
"ethereum-types": "^2.2.0-beta.0", "ethereum-types": "^2.2.0-beta.0",
"ethereumjs-util": "^5.1.1", "ethereumjs-util": "^5.1.1"
"lodash": "^4.17.11"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"

View File

@ -1,4 +1,17 @@
[ [
{
"version": "0.1.0-beta.1",
"changes": [
{
"note": "Add `encodeStaticCallAssetData` and `decodeStaticCallAssetData` in LibAssetData",
"pr": 2034
},
{
"note": "Add `revertIfInvalidAssetData` in LibAssetData",
"pr": 2034
}
]
},
{ {
"version": "0.1.0-beta.0", "version": "0.1.0-beta.0",
"changes": [ "changes": [

View File

@ -316,6 +316,29 @@ contract LibAssetData {
return (balances, allowances); return (balances, allowances);
} }
/// @dev Decode AssetProxy identifier
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
/// @return The AssetProxy identifier
function decodeAssetProxyId(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId
)
{
assetProxyId = assetData.readBytes4(0);
require(
assetProxyId == IAssetData(address(0)).ERC20Token.selector ||
assetProxyId == IAssetData(address(0)).ERC721Token.selector ||
assetProxyId == IAssetData(address(0)).ERC1155Assets.selector ||
assetProxyId == IAssetData(address(0)).MultiAsset.selector ||
assetProxyId == IAssetData(address(0)).StaticCall.selector,
"WRONG_PROXY_ID"
);
return assetProxyId;
}
/// @dev Encode ERC-20 asset data into the format described in the AssetProxy contract specification. /// @dev Encode ERC-20 asset data into the format described in the AssetProxy contract specification.
/// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded. /// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded.
/// @return AssetProxy-compliant data describing the asset. /// @return AssetProxy-compliant data describing the asset.
@ -330,7 +353,7 @@ contract LibAssetData {
/// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification. /// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset. /// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset.
/// @return The ERC-20 AssetProxy identifier, and the address of the ERC-20 /// @return The AssetProxy identifier, and the address of the ERC-20
/// contract hosting this asset. /// contract hosting this asset.
function decodeERC20AssetData(bytes memory assetData) function decodeERC20AssetData(bytes memory assetData)
public public
@ -515,4 +538,75 @@ contract LibAssetData {
); );
// solhint-enable indent // solhint-enable indent
} }
/// @dev Encode StaticCall asset data into the format described in the AssetProxy contract specification.
/// @param staticCallTargetAddress Target address of StaticCall.
/// @param staticCallData Data that will be passed to staticCallTargetAddress in the StaticCall.
/// @param expectedReturnDataHash Expected Keccak-256 hash of the StaticCall return data.
/// @return AssetProxy-compliant asset data describing the set of assets.
function encodeStaticCallAssetData(
address staticCallTargetAddress,
bytes memory staticCallData,
bytes32 expectedReturnDataHash
)
public
pure
returns (bytes memory assetData)
{
assetData = abi.encodeWithSelector(
IAssetData(address(0)).StaticCall.selector,
staticCallTargetAddress,
staticCallData,
expectedReturnDataHash
);
return assetData;
}
/// @dev Decode StaticCall asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing a StaticCall asset
/// @return The StaticCall AssetProxy identifier, the target address of the StaticCAll, the data to be
/// passed to the target address, and the expected Keccak-256 hash of the static call return data.
function decodeStaticCallAssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address staticCallTargetAddress,
bytes memory staticCallData,
bytes32 expectedReturnDataHash
)
{
assetProxyId = assetData.readBytes4(0);
require(
assetProxyId == IAssetData(address(0)).StaticCall.selector,
"WRONG_PROXY_ID"
);
(staticCallTargetAddress, staticCallData, expectedReturnDataHash) = abi.decode(
assetData.slice(4, assetData.length),
(address, bytes, bytes32)
);
}
function revertIfInvalidAssetData(bytes memory assetData)
public
pure
{
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
decodeERC20AssetData(assetData);
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
decodeERC721AssetData(assetData);
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
decodeERC1155AssetData(assetData);
} else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
decodeMultiAssetData(assetData);
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
decodeStaticCallAssetData(assetData);
} else {
revert("WRONG_PROXY_ID");
}
}
} }

View File

@ -72,6 +72,7 @@
"dependencies": { "dependencies": {
"@0x/base-contract": "^5.5.0-beta.0", "@0x/base-contract": "^5.5.0-beta.0",
"@0x/contracts-asset-proxy": "^2.3.0-beta.0", "@0x/contracts-asset-proxy": "^2.3.0-beta.0",
"@0x/contracts-dev-utils": "^0.1.0-beta.0",
"@0x/contracts-erc20": "^2.3.0-beta.0", "@0x/contracts-erc20": "^2.3.0-beta.0",
"@0x/contracts-erc721": "^2.2.0-beta.0", "@0x/contracts-erc721": "^2.2.0-beta.0",
"@0x/contracts-exchange": "^2.2.0-beta.0", "@0x/contracts-exchange": "^2.2.0-beta.0",

View File

@ -1,4 +1,25 @@
[ [
{
"version": "2.2.0-beta.1",
"changes": [
{
"note": "LocalBalanceStore.create and constructor now require an instance of DevUtilsContract",
"pr": 2304
},
{
"note": "In LocalBalanceStore, `transferAsset` is now `transferAssetAsync`",
"pr": 2304
},
{
"note": "Test utility classes AssetWrapper, MatchOrderTester, and OrderFactoryFromScenario constructors now require an instance of DevUtilsContract",
"pr": 2304
},
{
"note": "In OrderFactoryFromScenario, `generateOrder` is now `generateOrderAsync`",
"pr": 2304
}
]
},
{ {
"version": "2.2.0-beta.0", "version": "2.2.0-beta.0",
"changes": [ "changes": [

View File

@ -76,6 +76,7 @@
"dependencies": { "dependencies": {
"@0x/base-contract": "^5.5.0-beta.0", "@0x/base-contract": "^5.5.0-beta.0",
"@0x/contracts-asset-proxy": "^2.3.0-beta.0", "@0x/contracts-asset-proxy": "^2.3.0-beta.0",
"@0x/contracts-dev-utils": "^0.1.0-beta.0",
"@0x/contracts-erc1155": "^1.2.0-beta.0", "@0x/contracts-erc1155": "^1.2.0-beta.0",
"@0x/contracts-erc20": "^2.3.0-beta.0", "@0x/contracts-erc20": "^2.3.0-beta.0",
"@0x/contracts-erc721": "^2.2.0-beta.0", "@0x/contracts-erc721": "^2.2.0-beta.0",

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs'; import { ReferenceFunctions as LibReferenceFunctions } from '@0x/contracts-exchange-libs';
import { import {
constants, constants,
@ -24,68 +25,8 @@ import {
} from '../../src'; } from '../../src';
export class FillOrderWrapper { export class FillOrderWrapper {
private readonly _exchange: ExchangeContract;
private readonly _blockchainBalanceStore: BlockchainBalanceStore; private readonly _blockchainBalanceStore: BlockchainBalanceStore;
/**
* Locally simulates filling an order.
* @param txReceipt Transaction receipt from the actual fill, needed to update eth balance
* @param signedOrder The order being filled.
* @param takerAddress Address of taker (the address who matched the two orders)
* @param opts Optionally specifies the amount to fill.
* @param initBalanceStore Account balances prior to the fill.
* @return The expected account balances, fill results, and fill events.
*/
public static simulateFillOrder(
txReceipt: TransactionReceiptWithDecodedLogs,
signedOrder: SignedOrder,
takerAddress: string,
initBalanceStore: BalanceStore,
opts: { takerAssetFillAmount?: BigNumber } = {},
): [FillResults, FillEventArgs, BalanceStore] {
const balanceStore = LocalBalanceStore.create(initBalanceStore);
const takerAssetFillAmount =
opts.takerAssetFillAmount !== undefined ? opts.takerAssetFillAmount : signedOrder.takerAssetAmount;
// TODO(jalextowle): Change this if the integration tests take protocol fees into account.
const fillResults = LibReferenceFunctions.calculateFillResults(
signedOrder,
takerAssetFillAmount,
constants.ZERO_AMOUNT,
constants.ZERO_AMOUNT,
);
const fillEvent = FillOrderWrapper.simulateFillEvent(signedOrder, takerAddress, fillResults);
// Taker -> Maker
balanceStore.transferAsset(
takerAddress,
signedOrder.makerAddress,
fillResults.takerAssetFilledAmount,
signedOrder.takerAssetData,
);
// Maker -> Taker
balanceStore.transferAsset(
signedOrder.makerAddress,
takerAddress,
fillResults.makerAssetFilledAmount,
signedOrder.makerAssetData,
);
// Taker -> Fee Recipient
balanceStore.transferAsset(
takerAddress,
signedOrder.feeRecipientAddress,
fillResults.takerFeePaid,
signedOrder.takerFeeAssetData,
);
// Maker -> Fee Recipient
balanceStore.transferAsset(
signedOrder.makerAddress,
signedOrder.feeRecipientAddress,
fillResults.makerFeePaid,
signedOrder.makerFeeAssetData,
);
balanceStore.burnGas(txReceipt.from, constants.DEFAULT_GAS_PRICE * txReceipt.gasUsed);
return [fillResults, fillEvent, balanceStore];
}
/** /**
* Simulates the event emitted by the exchange contract when an order is filled. * Simulates the event emitted by the exchange contract when an order is filled.
*/ */
@ -119,6 +60,65 @@ export class FillOrderWrapper {
return events.map(event => _.pick(event, fieldsOfInterest)) as FillEventArgs[]; return events.map(event => _.pick(event, fieldsOfInterest)) as FillEventArgs[];
} }
/**
* Locally simulates filling an order.
* @param txReceipt Transaction receipt from the actual fill, needed to update eth balance
* @param signedOrder The order being filled.
* @param takerAddress Address of taker (the address who matched the two orders)
* @param opts Optionally specifies the amount to fill.
* @param initBalanceStore Account balances prior to the fill.
* @return The expected account balances, fill results, and fill events.
*/
public async simulateFillOrderAsync(
txReceipt: TransactionReceiptWithDecodedLogs,
signedOrder: SignedOrder,
takerAddress: string,
initBalanceStore: BalanceStore,
opts: { takerAssetFillAmount?: BigNumber } = {},
): Promise<[FillResults, FillEventArgs, BalanceStore]> {
const balanceStore = LocalBalanceStore.create(this._devUtils, initBalanceStore);
const takerAssetFillAmount =
opts.takerAssetFillAmount !== undefined ? opts.takerAssetFillAmount : signedOrder.takerAssetAmount;
// TODO(jalextowle): Change this if the integration tests take protocol fees into account.
const fillResults = LibReferenceFunctions.calculateFillResults(
signedOrder,
takerAssetFillAmount,
constants.ZERO_AMOUNT,
constants.ZERO_AMOUNT,
);
const fillEvent = FillOrderWrapper.simulateFillEvent(signedOrder, takerAddress, fillResults);
// Taker -> Maker
await balanceStore.transferAssetAsync(
takerAddress,
signedOrder.makerAddress,
fillResults.takerAssetFilledAmount,
signedOrder.takerAssetData,
);
// Maker -> Taker
await balanceStore.transferAssetAsync(
signedOrder.makerAddress,
takerAddress,
fillResults.makerAssetFilledAmount,
signedOrder.makerAssetData,
);
// Taker -> Fee Recipient
await balanceStore.transferAssetAsync(
takerAddress,
signedOrder.feeRecipientAddress,
fillResults.takerFeePaid,
signedOrder.takerFeeAssetData,
);
// Maker -> Fee Recipient
await balanceStore.transferAssetAsync(
signedOrder.makerAddress,
signedOrder.feeRecipientAddress,
fillResults.makerFeePaid,
signedOrder.makerFeeAssetData,
);
balanceStore.burnGas(txReceipt.from, constants.DEFAULT_GAS_PRICE * txReceipt.gasUsed);
return [fillResults, fillEvent, balanceStore];
}
/** /**
* Constructor. * Constructor.
* @param exchangeContract Instance of the deployed exchange contract. * @param exchangeContract Instance of the deployed exchange contract.
@ -127,12 +127,12 @@ export class FillOrderWrapper {
* @param tokenIds The tokenIds of ERC721 and ERC1155 assets to assert the balances of. * @param tokenIds The tokenIds of ERC721 and ERC1155 assets to assert the balances of.
*/ */
public constructor( public constructor(
exchangeContract: ExchangeContract, private readonly _exchange: ExchangeContract,
private readonly _devUtils: DevUtilsContract,
tokenOwnersByName: TokenOwnersByName, tokenOwnersByName: TokenOwnersByName,
tokenContractsByName: Partial<TokenContractsByName>, tokenContractsByName: Partial<TokenContractsByName>,
tokenIds: Partial<TokenIds>, tokenIds: Partial<TokenIds>,
) { ) {
this._exchange = exchangeContract;
this._blockchainBalanceStore = new BlockchainBalanceStore(tokenOwnersByName, tokenContractsByName, tokenIds); this._blockchainBalanceStore = new BlockchainBalanceStore(tokenOwnersByName, tokenContractsByName, tokenIds);
} }
@ -168,7 +168,7 @@ export class FillOrderWrapper {
simulatedFillResults, simulatedFillResults,
simulatedFillEvent, simulatedFillEvent,
simulatedFinalBalanceStore, simulatedFinalBalanceStore,
] = FillOrderWrapper.simulateFillOrder(txReceipt, signedOrder, from, this._blockchainBalanceStore, opts); ] = await this.simulateFillOrderAsync(txReceipt, signedOrder, from, this._blockchainBalanceStore, opts);
// Assert state transition // Assert state transition
expect(simulatedFillResults, 'Fill Results').to.be.deep.equal(fillResults); expect(simulatedFillResults, 'Fill Results').to.be.deep.equal(fillResults);
expect(simulatedFillEvent, 'Fill Events').to.be.deep.equal(fillEvent); expect(simulatedFillEvent, 'Fill Events').to.be.deep.equal(fillEvent);

View File

@ -1,5 +1,5 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, Numberish } from '@0x/contracts-test-utils'; import { constants, Numberish } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId } from '@0x/types'; import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -12,8 +12,8 @@ export class LocalBalanceStore extends BalanceStore {
* Creates a new balance store based on an existing one. * Creates a new balance store based on an existing one.
* @param sourceBalanceStore Existing balance store whose values should be copied. * @param sourceBalanceStore Existing balance store whose values should be copied.
*/ */
public static create(sourceBalanceStore?: BalanceStore): LocalBalanceStore { public static create(devUtils: DevUtilsContract, sourceBalanceStore?: BalanceStore): LocalBalanceStore {
const localBalanceStore = new LocalBalanceStore(); const localBalanceStore = new LocalBalanceStore(devUtils);
if (sourceBalanceStore !== undefined) { if (sourceBalanceStore !== undefined) {
localBalanceStore.cloneFrom(sourceBalanceStore); localBalanceStore.cloneFrom(sourceBalanceStore);
} }
@ -26,6 +26,7 @@ export class LocalBalanceStore extends BalanceStore {
* be initialized via `create`. * be initialized via `create`.
*/ */
protected constructor( protected constructor(
private readonly _devUtils: DevUtilsContract,
tokenOwnersByName: TokenOwnersByName = {}, tokenOwnersByName: TokenOwnersByName = {},
tokenContractsByName: Partial<TokenContractsByName> = {}, tokenContractsByName: Partial<TokenContractsByName> = {},
) { ) {
@ -71,27 +72,33 @@ export class LocalBalanceStore extends BalanceStore {
* @param amount Amount of asset(s) to transfer * @param amount Amount of asset(s) to transfer
* @param assetData Asset data of assets being transferred. * @param assetData Asset data of assets being transferred.
*/ */
public transferAsset(fromAddress: string, toAddress: string, amount: BigNumber, assetData: string): void { public async transferAssetAsync(
fromAddress: string,
toAddress: string,
amount: BigNumber,
assetData: string,
): Promise<void> {
if (fromAddress === toAddress) { if (fromAddress === toAddress) {
return; return;
} }
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); const assetProxyId = await this._devUtils.decodeAssetProxyId.callAsync(assetData);
switch (assetProxyId) { switch (assetProxyId) {
case AssetProxyId.ERC20: { case AssetProxyId.ERC20: {
const erc20AssetData = assetDataUtils.decodeERC20AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const assetAddress = erc20AssetData.tokenAddress; const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData.callAsync(assetData);
_.update(this._balances.erc20, [fromAddress, assetAddress], balance => balance.minus(amount)); _.update(this._balances.erc20, [fromAddress, tokenAddress], balance => balance.minus(amount));
_.update(this._balances.erc20, [toAddress, assetAddress], balance => _.update(this._balances.erc20, [toAddress, tokenAddress], balance =>
(balance || constants.ZERO_AMOUNT).plus(amount), (balance || constants.ZERO_AMOUNT).plus(amount),
); );
break; break;
} }
case AssetProxyId.ERC721: { case AssetProxyId.ERC721: {
const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const assetAddress = erc721AssetData.tokenAddress; const [proxyId, tokenAddress, tokenId] = await this._devUtils.decodeERC721AssetData.callAsync(
const tokenId = erc721AssetData.tokenId; assetData,
const fromTokens = _.get(this._balances.erc721, [fromAddress, assetAddress], []); );
const toTokens = _.get(this._balances.erc721, [toAddress, assetAddress], []); const fromTokens = _.get(this._balances.erc721, [fromAddress, tokenAddress], []);
const toTokens = _.get(this._balances.erc721, [toAddress, tokenAddress], []);
if (amount.gte(1)) { if (amount.gte(1)) {
const tokenIndex = _.findIndex(fromTokens as BigNumber[], t => t.eq(tokenId)); const tokenIndex = _.findIndex(fromTokens as BigNumber[], t => t.eq(tokenId));
if (tokenIndex !== -1) { if (tokenIndex !== -1) {
@ -100,25 +107,29 @@ export class LocalBalanceStore extends BalanceStore {
toTokens.sort(); toTokens.sort();
} }
} }
_.set(this._balances.erc721, [fromAddress, assetAddress], fromTokens); _.set(this._balances.erc721, [fromAddress, tokenAddress], fromTokens);
_.set(this._balances.erc721, [toAddress, assetAddress], toTokens); _.set(this._balances.erc721, [toAddress, tokenAddress], toTokens);
break; break;
} }
case AssetProxyId.ERC1155: { case AssetProxyId.ERC1155: {
const erc1155AssetData = assetDataUtils.decodeERC1155AssetData(assetData); const [
const assetAddress = erc1155AssetData.tokenAddress; proxyId, // tslint:disable-line:no-unused-variable
tokenAddress,
tokenIds,
tokenValues,
] = await this._devUtils.decodeERC1155AssetData.callAsync(assetData);
const fromBalances = { const fromBalances = {
// tslint:disable-next-line:no-inferred-empty-object-type // tslint:disable-next-line:no-inferred-empty-object-type
fungible: _.get(this._balances.erc1155, [fromAddress, assetAddress, 'fungible'], {}), fungible: _.get(this._balances.erc1155, [fromAddress, tokenAddress, 'fungible'], {}),
nonFungible: _.get(this._balances.erc1155, [fromAddress, assetAddress, 'nonFungible'], []), nonFungible: _.get(this._balances.erc1155, [fromAddress, tokenAddress, 'nonFungible'], []),
}; };
const toBalances = { const toBalances = {
// tslint:disable-next-line:no-inferred-empty-object-type // tslint:disable-next-line:no-inferred-empty-object-type
fungible: _.get(this._balances.erc1155, [toAddress, assetAddress, 'fungible'], {}), fungible: _.get(this._balances.erc1155, [toAddress, tokenAddress, 'fungible'], {}),
nonFungible: _.get(this._balances.erc1155, [toAddress, assetAddress, 'nonFungible'], []), nonFungible: _.get(this._balances.erc1155, [toAddress, tokenAddress, 'nonFungible'], []),
}; };
for (const [i, tokenId] of erc1155AssetData.tokenIds.entries()) { for (const [i, tokenId] of tokenIds.entries()) {
const tokenValue = erc1155AssetData.tokenValues[i]; const tokenValue = tokenValues[i];
const tokenAmount = amount.times(tokenValue); const tokenAmount = amount.times(tokenValue);
if (tokenAmount.gt(0)) { if (tokenAmount.gt(0)) {
const tokenIndex = _.findIndex(fromBalances.nonFungible as BigNumber[], t => t.eq(tokenId)); const tokenIndex = _.findIndex(fromBalances.nonFungible as BigNumber[], t => t.eq(tokenId));
@ -138,16 +149,18 @@ export class LocalBalanceStore extends BalanceStore {
} }
} }
} }
_.set(this._balances.erc1155, [fromAddress, assetAddress], fromBalances); _.set(this._balances.erc1155, [fromAddress, tokenAddress], fromBalances);
_.set(this._balances.erc1155, [toAddress, assetAddress], toBalances); _.set(this._balances.erc1155, [toAddress, tokenAddress], toBalances);
break; break;
} }
case AssetProxyId.MultiAsset: { case AssetProxyId.MultiAsset: {
const multiAssetData = assetDataUtils.decodeMultiAssetData(assetData); // tslint:disable-next-line:no-unused-variable
for (const i of _.times(multiAssetData.amounts.length)) { const [proxyId, amounts, nestedAssetData] = await this._devUtils.decodeMultiAssetData.callAsync(
const nestedAmount = amount.times(multiAssetData.amounts[i]); assetData,
const nestedAssetData = multiAssetData.nestedAssetData[i]; );
this.transferAsset(fromAddress, toAddress, nestedAmount, nestedAssetData); for (const [i, amt] of amounts.entries()) {
const nestedAmount = amount.times(amt);
await this.transferAssetAsync(fromAddress, toAddress, nestedAmount, nestedAssetData[i]);
} }
break; break;
} }

View File

@ -10,6 +10,7 @@ import {
StaticCallProxyContract, StaticCallProxyContract,
TestStaticCallTargetContract, TestStaticCallTargetContract,
} from '@0x/contracts-asset-proxy'; } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { ERC1155MintableContract } from '@0x/contracts-erc1155'; import { ERC1155MintableContract } from '@0x/contracts-erc1155';
import { import {
artifacts as erc20Artifacts, artifacts as erc20Artifacts,
@ -32,7 +33,7 @@ import {
txDefaults, txDefaults,
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { assetDataUtils, ExchangeRevertErrors, LibMathRevertErrors, orderHashUtils } from '@0x/order-utils'; import { ExchangeRevertErrors, LibMathRevertErrors, orderHashUtils } from '@0x/order-utils';
import { RevertReason, SignatureType, SignedOrder } from '@0x/types'; import { RevertReason, SignatureType, SignedOrder } from '@0x/types';
import { BigNumber, providerUtils, StringRevertError } from '@0x/utils'; import { BigNumber, providerUtils, StringRevertError } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
@ -59,6 +60,7 @@ blockchainTests.resets('Exchange core', () => {
let takerAddress: string; let takerAddress: string;
let feeRecipientAddress: string; let feeRecipientAddress: string;
let devUtils: DevUtilsContract;
let erc20TokenA: DummyERC20TokenContract; let erc20TokenA: DummyERC20TokenContract;
let erc20TokenB: DummyERC20TokenContract; let erc20TokenB: DummyERC20TokenContract;
let feeToken: DummyERC20TokenContract; let feeToken: DummyERC20TokenContract;
@ -100,6 +102,7 @@ blockchainTests.resets('Exchange core', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = _.slice(accounts, 0, 4)); const usedAddresses = ([owner, makerAddress, takerAddress, feeRecipientAddress] = _.slice(accounts, 0, 4));
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner); erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner); erc1155ProxyWrapper = new ERC1155ProxyWrapper(provider, usedAddresses, owner);
@ -213,10 +216,10 @@ blockchainTests.resets('Exchange core', () => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress, makerAddress,
feeRecipientAddress, feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultMakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerAssetAddress),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeAssetAddress), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultFeeAssetAddress),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeAssetAddress), takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultFeeAssetAddress),
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId, chainId,
}; };
@ -239,6 +242,7 @@ blockchainTests.resets('Exchange core', () => {
}; };
fillOrderWrapper = new FillOrderWrapper( fillOrderWrapper = new FillOrderWrapper(
exchange, exchange,
devUtils,
{ makerAddress, takerAddress, feeRecipientAddress }, { makerAddress, takerAddress, feeRecipientAddress },
tokenContracts, tokenContracts,
tokenIds, tokenIds,
@ -421,9 +425,9 @@ blockchainTests.resets('Exchange core', () => {
describe('Fill transfer ordering', () => { describe('Fill transfer ordering', () => {
it('should allow the maker to exchange assets received by the taker', async () => { it('should allow the maker to exchange assets received by the taker', async () => {
// Set maker/taker assetData to the same asset // Set maker/taker assetData to the same asset
const takerAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const takerAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const takerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1);
const makerAssetData = assetDataUtils.encodeMultiAssetData([takerAssetAmount], [takerAssetData]); const makerAssetData = await devUtils.encodeMultiAssetData.callAsync([takerAssetAmount], [takerAssetData]);
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData, makerAssetData,
takerAssetData, takerAssetData,
@ -439,7 +443,7 @@ blockchainTests.resets('Exchange core', () => {
await fillOrderWrapper.fillOrderAndAssertEffectsAsync(signedOrder, takerAddress); await fillOrderWrapper.fillOrderAndAssertEffectsAsync(signedOrder, takerAddress);
}); });
it('should allow the taker to pay fees with an asset that received by the maker', async () => { it('should allow the taker to pay fees with an asset that received by the maker', async () => {
const makerAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const makerAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
takerFeeAssetData: makerAssetData, takerFeeAssetData: makerAssetData,
makerFee: constants.ZERO_AMOUNT, makerFee: constants.ZERO_AMOUNT,
@ -452,7 +456,7 @@ blockchainTests.resets('Exchange core', () => {
await fillOrderWrapper.fillOrderAndAssertEffectsAsync(signedOrder, takerAddress); await fillOrderWrapper.fillOrderAndAssertEffectsAsync(signedOrder, takerAddress);
}); });
it('should allow the maker to pay fees with an asset that received by the taker', async () => { it('should allow the maker to pay fees with an asset that received by the taker', async () => {
const takerAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenB.address); const takerAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address);
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerFeeAssetData: takerAssetData, makerFeeAssetData: takerAssetData,
makerFee: new BigNumber(1), makerFee: new BigNumber(1),
@ -479,7 +483,7 @@ blockchainTests.resets('Exchange core', () => {
}); });
it('should transfer the correct amounts when makerAssetAmount === takerAssetAmount', async () => { it('should transfer the correct amounts when makerAssetAmount === takerAssetAmount', async () => {
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(noReturnErc20Token.address),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
}); });
@ -487,7 +491,7 @@ blockchainTests.resets('Exchange core', () => {
}); });
it('should transfer the correct amounts when makerAssetAmount > takerAssetAmount', async () => { it('should transfer the correct amounts when makerAssetAmount > takerAssetAmount', async () => {
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(noReturnErc20Token.address),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
}); });
@ -495,7 +499,7 @@ blockchainTests.resets('Exchange core', () => {
}); });
it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount', async () => { it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount', async () => {
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(noReturnErc20Token.address),
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),
}); });
@ -672,8 +676,8 @@ blockchainTests.resets('Exchange core', () => {
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1), makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), takerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, takerAssetId),
}); });
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
// Verify pre-conditions // Verify pre-conditions
@ -699,8 +703,8 @@ blockchainTests.resets('Exchange core', () => {
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1), makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), takerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, takerAssetId),
}); });
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
// Verify pre-conditions // Verify pre-conditions
@ -726,8 +730,8 @@ blockchainTests.resets('Exchange core', () => {
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(2), makerAssetAmount: new BigNumber(2),
takerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), takerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, takerAssetId),
}); });
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
// Verify pre-conditions // Verify pre-conditions
@ -753,8 +757,8 @@ blockchainTests.resets('Exchange core', () => {
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1), makerAssetAmount: new BigNumber(1),
takerAssetAmount: new BigNumber(500), takerAssetAmount: new BigNumber(500),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), takerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, takerAssetId),
}); });
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
// Verify pre-conditions // Verify pre-conditions
@ -779,8 +783,8 @@ blockchainTests.resets('Exchange core', () => {
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetAmount: new BigNumber(1), makerAssetAmount: new BigNumber(1),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId), makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, makerAssetId),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerAssetAddress),
}); });
// Call Exchange // Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
@ -798,12 +802,12 @@ blockchainTests.resets('Exchange core', () => {
it('should allow multiple assets to be exchanged for a single asset', async () => { it('should allow multiple assets to be exchanged for a single asset', async () => {
const makerAmounts = [new BigNumber(10), new BigNumber(20)]; const makerAmounts = [new BigNumber(10), new BigNumber(20)];
const makerNestedAssetData = [ const makerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(erc20TokenA.address), await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address),
assetDataUtils.encodeERC20AssetData(erc20TokenB.address), await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address),
]; ];
const makerAssetData = assetDataUtils.encodeMultiAssetData(makerAmounts, makerNestedAssetData); const makerAssetData = await devUtils.encodeMultiAssetData.callAsync(makerAmounts, makerNestedAssetData);
const makerAssetAmount = new BigNumber(1); const makerAssetAmount = new BigNumber(1);
const takerAssetData = assetDataUtils.encodeERC20AssetData(feeToken.address); const takerAssetData = await devUtils.encodeERC20AssetData.callAsync(feeToken.address);
const takerAssetAmount = new BigNumber(10); const takerAssetAmount = new BigNumber(10);
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData, makerAssetData,
@ -818,18 +822,18 @@ blockchainTests.resets('Exchange core', () => {
it('should allow multiple assets to be exchanged for multiple assets', async () => { it('should allow multiple assets to be exchanged for multiple assets', async () => {
const makerAmounts = [new BigNumber(10), new BigNumber(20)]; const makerAmounts = [new BigNumber(10), new BigNumber(20)];
const makerNestedAssetData = [ const makerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(erc20TokenA.address), await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address),
assetDataUtils.encodeERC20AssetData(erc20TokenB.address), await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address),
]; ];
const makerAssetData = assetDataUtils.encodeMultiAssetData(makerAmounts, makerNestedAssetData); const makerAssetData = await devUtils.encodeMultiAssetData.callAsync(makerAmounts, makerNestedAssetData);
const makerAssetAmount = new BigNumber(1); const makerAssetAmount = new BigNumber(1);
const takerAmounts = [new BigNumber(10), new BigNumber(1)]; const takerAmounts = [new BigNumber(10), new BigNumber(1)];
const takerAssetId = erc721TakerAssetIds[0]; const takerAssetId = erc721TakerAssetIds[0];
const takerNestedAssetData = [ const takerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(feeToken.address), await devUtils.encodeERC20AssetData.callAsync(feeToken.address),
assetDataUtils.encodeERC721AssetData(erc721Token.address, takerAssetId), await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, takerAssetId),
]; ];
const takerAssetData = assetDataUtils.encodeMultiAssetData(takerAmounts, takerNestedAssetData); const takerAssetData = await devUtils.encodeMultiAssetData.callAsync(takerAmounts, takerNestedAssetData);
const takerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1);
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData, makerAssetData,
@ -844,12 +848,12 @@ blockchainTests.resets('Exchange core', () => {
it('should allow an order selling multiple assets to be partially filled', async () => { it('should allow an order selling multiple assets to be partially filled', async () => {
const makerAmounts = [new BigNumber(10), new BigNumber(20)]; const makerAmounts = [new BigNumber(10), new BigNumber(20)];
const makerNestedAssetData = [ const makerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(erc20TokenA.address), await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address),
assetDataUtils.encodeERC20AssetData(erc20TokenB.address), await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address),
]; ];
const makerAssetData = assetDataUtils.encodeMultiAssetData(makerAmounts, makerNestedAssetData); const makerAssetData = await devUtils.encodeMultiAssetData.callAsync(makerAmounts, makerNestedAssetData);
const makerAssetAmount = new BigNumber(30); const makerAssetAmount = new BigNumber(30);
const takerAssetData = assetDataUtils.encodeERC20AssetData(feeToken.address); const takerAssetData = await devUtils.encodeERC20AssetData.callAsync(feeToken.address);
const takerAssetAmount = new BigNumber(10); const takerAssetAmount = new BigNumber(10);
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData, makerAssetData,
@ -866,12 +870,12 @@ blockchainTests.resets('Exchange core', () => {
it('should allow an order buying multiple assets to be partially filled', async () => { it('should allow an order buying multiple assets to be partially filled', async () => {
const takerAmounts = [new BigNumber(10), new BigNumber(20)]; const takerAmounts = [new BigNumber(10), new BigNumber(20)];
const takerNestedAssetData = [ const takerNestedAssetData = [
assetDataUtils.encodeERC20AssetData(erc20TokenA.address), await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address),
assetDataUtils.encodeERC20AssetData(erc20TokenB.address), await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address),
]; ];
const takerAssetData = assetDataUtils.encodeMultiAssetData(takerAmounts, takerNestedAssetData); const takerAssetData = await devUtils.encodeMultiAssetData.callAsync(takerAmounts, takerNestedAssetData);
const takerAssetAmount = new BigNumber(30); const takerAssetAmount = new BigNumber(30);
const makerAssetData = assetDataUtils.encodeERC20AssetData(feeToken.address); const makerAssetData = await devUtils.encodeERC20AssetData.callAsync(feeToken.address);
const makerAssetAmount = new BigNumber(10); const makerAssetAmount = new BigNumber(10);
signedOrder = await orderFactory.newSignedOrderAsync({ signedOrder = await orderFactory.newSignedOrderAsync({
makerAssetData, makerAssetData,
@ -897,13 +901,13 @@ blockchainTests.resets('Exchange core', () => {
const makerAssetAmount = new BigNumber(1); const makerAssetAmount = new BigNumber(1);
const takerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1);
const receiverCallbackData = '0x'; const receiverCallbackData = '0x';
const makerAssetData = assetDataUtils.encodeERC1155AssetData( const makerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
makerAssetsToTransfer, makerAssetsToTransfer,
makerValuesToTransfer, makerValuesToTransfer,
receiverCallbackData, receiverCallbackData,
); );
const takerAssetData = assetDataUtils.encodeERC1155AssetData( const takerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
takerAssetsToTransfer, takerAssetsToTransfer,
takerValuesToTransfer, takerValuesToTransfer,
@ -932,13 +936,13 @@ blockchainTests.resets('Exchange core', () => {
const makerAssetAmount = new BigNumber(1); const makerAssetAmount = new BigNumber(1);
const takerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1);
const receiverCallbackData = '0x'; const receiverCallbackData = '0x';
const makerAssetData = assetDataUtils.encodeERC1155AssetData( const makerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
makerAssetsToTransfer, makerAssetsToTransfer,
makerValuesToTransfer, makerValuesToTransfer,
receiverCallbackData, receiverCallbackData,
); );
const takerAssetData = assetDataUtils.encodeERC1155AssetData( const takerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
takerAssetsToTransfer, takerAssetsToTransfer,
takerValuesToTransfer, takerValuesToTransfer,
@ -966,13 +970,13 @@ blockchainTests.resets('Exchange core', () => {
const makerAssetAmount = new BigNumber(1); const makerAssetAmount = new BigNumber(1);
const takerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1);
const receiverCallbackData = '0x'; const receiverCallbackData = '0x';
const makerAssetData = assetDataUtils.encodeERC1155AssetData( const makerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
makerAssetsToTransfer, makerAssetsToTransfer,
makerValuesToTransfer, makerValuesToTransfer,
receiverCallbackData, receiverCallbackData,
); );
const takerAssetData = assetDataUtils.encodeERC1155AssetData( const takerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
takerAssetsToTransfer, takerAssetsToTransfer,
takerValuesToTransfer, takerValuesToTransfer,
@ -1006,13 +1010,13 @@ blockchainTests.resets('Exchange core', () => {
const makerAssetAmount = new BigNumber(1); const makerAssetAmount = new BigNumber(1);
const takerAssetAmount = new BigNumber(1); const takerAssetAmount = new BigNumber(1);
const receiverCallbackData = '0x'; const receiverCallbackData = '0x';
const makerAssetData = assetDataUtils.encodeERC1155AssetData( const makerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
makerAssetsToTransfer, makerAssetsToTransfer,
makerValuesToTransfer, makerValuesToTransfer,
receiverCallbackData, receiverCallbackData,
); );
const takerAssetData = assetDataUtils.encodeERC1155AssetData( const takerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
takerAssetsToTransfer, takerAssetsToTransfer,
takerValuesToTransfer, takerValuesToTransfer,
@ -1051,13 +1055,13 @@ blockchainTests.resets('Exchange core', () => {
const makerAssetAmount = new BigNumber(10); const makerAssetAmount = new BigNumber(10);
const takerAssetAmount = new BigNumber(20); const takerAssetAmount = new BigNumber(20);
const receiverCallbackData = '0x'; const receiverCallbackData = '0x';
const makerAssetData = assetDataUtils.encodeERC1155AssetData( const makerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
makerAssetsToTransfer, makerAssetsToTransfer,
makerValuesToTransfer, makerValuesToTransfer,
receiverCallbackData, receiverCallbackData,
); );
const takerAssetData = assetDataUtils.encodeERC1155AssetData( const takerAssetData = await devUtils.encodeERC1155AssetData.callAsync(
erc1155Contract.address, erc1155Contract.address,
takerAssetsToTransfer, takerAssetsToTransfer,
takerValuesToTransfer, takerValuesToTransfer,
@ -1088,7 +1092,7 @@ blockchainTests.resets('Exchange core', () => {
}); });
it('should revert if the staticcall is unsuccessful', async () => { it('should revert if the staticcall is unsuccessful', async () => {
const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1)); const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
constants.KECCAK256_NULL, constants.KECCAK256_NULL,
@ -1107,7 +1111,7 @@ blockchainTests.resets('Exchange core', () => {
const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData( const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(
constants.ZERO_AMOUNT, constants.ZERO_AMOUNT,
); );
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
constants.KECCAK256_NULL, constants.KECCAK256_NULL,
@ -1117,14 +1121,14 @@ blockchainTests.resets('Exchange core', () => {
}); });
it('should revert if the staticcall is unsuccessful using the MultiAssetProxy', async () => { it('should revert if the staticcall is unsuccessful using the MultiAssetProxy', async () => {
const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1)); const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
const staticCallAssetData = assetDataUtils.encodeStaticCallAssetData( const staticCallAssetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
constants.KECCAK256_NULL, constants.KECCAK256_NULL,
); );
const assetData = assetDataUtils.encodeMultiAssetData( const assetData = await devUtils.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)], [new BigNumber(1), new BigNumber(1)],
[assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), staticCallAssetData], [await devUtils.encodeERC20AssetData.callAsync(defaultMakerAssetAddress), staticCallAssetData],
); );
signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetData }); signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetData });
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder); const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
@ -1140,14 +1144,14 @@ blockchainTests.resets('Exchange core', () => {
const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData( const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(
constants.ZERO_AMOUNT, constants.ZERO_AMOUNT,
); );
const staticCallAssetData = assetDataUtils.encodeStaticCallAssetData( const staticCallAssetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
constants.KECCAK256_NULL, constants.KECCAK256_NULL,
); );
const assetData = assetDataUtils.encodeMultiAssetData( const assetData = await devUtils.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)], [new BigNumber(1), new BigNumber(1)],
[assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), staticCallAssetData], [await devUtils.encodeERC20AssetData.callAsync(defaultMakerAssetAddress), staticCallAssetData],
); );
signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetData }); signedOrder = await orderFactory.newSignedOrderAsync({ makerAssetData: assetData });
await fillOrderWrapper.fillOrderAndAssertEffectsAsync(signedOrder, takerAddress); await fillOrderWrapper.fillOrderAndAssertEffectsAsync(signedOrder, takerAddress);

View File

@ -5,6 +5,7 @@ import {
ERC721ProxyContract, ERC721ProxyContract,
ERC721Wrapper, ERC721Wrapper,
} from '@0x/contracts-asset-proxy'; } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import {
chaiSetup, chaiSetup,
@ -16,7 +17,7 @@ import {
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, ExchangeRevertErrors } from '@0x/order-utils'; import { ExchangeRevertErrors } from '@0x/order-utils';
import { AssetProxyId, RevertReason } from '@0x/types'; import { AssetProxyId, RevertReason } from '@0x/types';
import { BigNumber, OwnableRevertErrors, StringRevertError } from '@0x/utils'; import { BigNumber, OwnableRevertErrors, StringRevertError } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -50,6 +51,7 @@ describe('AssetProxyDispatcher', () => {
let erc20Wrapper: ERC20Wrapper; let erc20Wrapper: ERC20Wrapper;
let erc721Wrapper: ERC721Wrapper; let erc721Wrapper: ERC721Wrapper;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
before(async () => { before(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
}); });
@ -191,7 +193,7 @@ describe('AssetProxyDispatcher', () => {
from: owner, from: owner,
}); });
// Construct metadata for ERC20 proxy // Construct metadata for ERC20 proxy
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync(); const erc20Balances = await erc20Wrapper.getBalancesAsync();
@ -220,7 +222,7 @@ describe('AssetProxyDispatcher', () => {
from: owner, from: owner,
}); });
// Construct metadata for ERC20 proxy // Construct metadata for ERC20 proxy
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync(); const erc20Balances = await erc20Wrapper.getBalancesAsync();
@ -240,7 +242,8 @@ describe('AssetProxyDispatcher', () => {
it('should revert if dispatching to unregistered proxy', async () => { it('should revert if dispatching to unregistered proxy', async () => {
// Construct metadata for ERC20 proxy // Construct metadata for ERC20 proxy
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10); const amount = new BigNumber(10);
const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError( const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError(
@ -263,7 +266,7 @@ describe('AssetProxyDispatcher', () => {
await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, {
from: owner, from: owner,
}); });
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address).slice(0, 8); const encodedAssetData = (await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address)).slice(0, 8);
const amount = new BigNumber(1); const amount = new BigNumber(1);
const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError( const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError(
ExchangeRevertErrors.AssetProxyDispatchErrorCode.InvalidAssetDataLength, ExchangeRevertErrors.AssetProxyDispatchErrorCode.InvalidAssetDataLength,
@ -286,7 +289,7 @@ describe('AssetProxyDispatcher', () => {
from: owner, from: owner,
}); });
// Shave off the last byte // Shave off the last byte
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address).slice(0, 72); const encodedAssetData = (await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address)).slice(0, 72);
const amount = new BigNumber(1); const amount = new BigNumber(1);
const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError( const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError(
ExchangeRevertErrors.AssetProxyDispatchErrorCode.InvalidAssetDataLength, ExchangeRevertErrors.AssetProxyDispatchErrorCode.InvalidAssetDataLength,
@ -311,7 +314,7 @@ describe('AssetProxyDispatcher', () => {
await erc20TokenA.approve.awaitTransactionSuccessAsync(erc20Proxy.address, constants.ZERO_AMOUNT, { await erc20TokenA.approve.awaitTransactionSuccessAsync(erc20Proxy.address, constants.ZERO_AMOUNT, {
from: makerAddress, from: makerAddress,
}); });
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const encodedAssetData = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const amount = new BigNumber(1); const amount = new BigNumber(1);
const nestedError = new StringRevertError(RevertReason.TransferFailed).encode(); const nestedError = new StringRevertError(RevertReason.TransferFailed).encode();
const expectedError = new ExchangeRevertErrors.AssetProxyTransferError( const expectedError = new ExchangeRevertErrors.AssetProxyTransferError(
@ -335,8 +338,8 @@ describe('AssetProxyDispatcher', () => {
await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, {
from: owner, from: owner,
}); });
const assetDataA = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const assetDataA = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const assetDataB = assetDataUtils.encodeERC20AssetData(erc20TokenB.address); const assetDataB = await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address);
await erc20TokenB.approve.awaitTransactionSuccessAsync(erc20Proxy.address, constants.ZERO_AMOUNT, { await erc20TokenB.approve.awaitTransactionSuccessAsync(erc20Proxy.address, constants.ZERO_AMOUNT, {
from: makerAddress, from: makerAddress,
}); });
@ -356,8 +359,8 @@ describe('AssetProxyDispatcher', () => {
return expect(tx).to.revertWith(expectedError); return expect(tx).to.revertWith(expectedError);
}); });
it('should forward the revert reason from the underlying failed transfer', async () => { it('should forward the revert reason from the underlying failed transfer', async () => {
const assetDataA = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const assetDataA = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const assetDataB = assetDataUtils.encodeERC20AssetData(erc20TokenB.address); const assetDataB = await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address);
const transferIndexAsBytes32 = '0x0000000000000000000000000000000000000000000000000000000000000000'; const transferIndexAsBytes32 = '0x0000000000000000000000000000000000000000000000000000000000000000';
const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError( const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError(
ExchangeRevertErrors.AssetProxyDispatchErrorCode.UnknownAssetProxy, ExchangeRevertErrors.AssetProxyDispatchErrorCode.UnknownAssetProxy,
@ -376,8 +379,8 @@ describe('AssetProxyDispatcher', () => {
await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, {
from: owner, from: owner,
}); });
const assetDataA = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const assetDataA = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const assetDataB = assetDataUtils.encodeERC20AssetData(erc20TokenB.address); const assetDataB = await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address);
const tx = assetProxyDispatcher.simulateDispatchTransferFromCalls.sendTransactionAsync( const tx = assetProxyDispatcher.simulateDispatchTransferFromCalls.sendTransactionAsync(
[assetDataA, assetDataB], [assetDataA, assetDataB],
[makerAddress, makerAddress], [makerAddress, makerAddress],
@ -390,8 +393,8 @@ describe('AssetProxyDispatcher', () => {
await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, { await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, {
from: owner, from: owner,
}); });
const assetDataA = assetDataUtils.encodeERC20AssetData(erc20TokenA.address); const assetDataA = await devUtils.encodeERC20AssetData.callAsync(erc20TokenA.address);
const assetDataB = assetDataUtils.encodeERC20AssetData(erc20TokenB.address); const assetDataB = await devUtils.encodeERC20AssetData.callAsync(erc20TokenB.address);
const balances = await erc20Wrapper.getBalancesAsync(); const balances = await erc20Wrapper.getBalancesAsync();
try { try {
await assetProxyDispatcher.simulateDispatchTransferFromCalls.awaitTransactionSuccessAsync( await assetProxyDispatcher.simulateDispatchTransferFromCalls.awaitTransactionSuccessAsync(

View File

@ -8,6 +8,7 @@ import {
ERC721Wrapper, ERC721Wrapper,
MultiAssetProxyContract, MultiAssetProxyContract,
} from '@0x/contracts-asset-proxy'; } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { ERC1155Contract as ERC1155TokenContract, Erc1155Wrapper as ERC1155Wrapper } from '@0x/contracts-erc1155'; import { ERC1155Contract as ERC1155TokenContract, Erc1155Wrapper as ERC1155Wrapper } from '@0x/contracts-erc1155';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { DummyERC721TokenContract } from '@0x/contracts-erc721'; import { DummyERC721TokenContract } from '@0x/contracts-erc721';
@ -22,7 +23,7 @@ import {
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils'; import { ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
import { OrderStatus, SignedOrder } from '@0x/types'; import { OrderStatus, SignedOrder } from '@0x/types';
import { BigNumber, providerUtils } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
@ -82,6 +83,7 @@ describe('matchOrders', () => {
let matchOrderTester: MatchOrderTester; let matchOrderTester: MatchOrderTester;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider, txDefaults);
before(async () => { before(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
}); });
@ -177,10 +179,10 @@ describe('matchOrders', () => {
const defaultOrderParamsLeft = { const defaultOrderParamsLeft = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress: makerAddressLeft, makerAddress: makerAddressLeft,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultFeeTokenAddress),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress), takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultFeeTokenAddress),
feeRecipientAddress: feeRecipientAddressLeft, feeRecipientAddress: feeRecipientAddressLeft,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId, chainId,
@ -188,10 +190,10 @@ describe('matchOrders', () => {
const defaultOrderParamsRight = { const defaultOrderParamsRight = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultFeeTokenAddress),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultFeeTokenAddress), takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultFeeTokenAddress),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
exchangeAddress: exchange.address, exchangeAddress: exchange.address,
chainId, chainId,
@ -201,7 +203,13 @@ describe('matchOrders', () => {
const privateKeyRight = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddressRight)]; const privateKeyRight = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddressRight)];
orderFactoryRight = new OrderFactory(privateKeyRight, defaultOrderParamsRight); orderFactoryRight = new OrderFactory(privateKeyRight, defaultOrderParamsRight);
// Create match order tester // Create match order tester
matchOrderTester = new MatchOrderTester(exchangeWrapper, erc20Wrapper, erc721Wrapper, erc1155ProxyWrapper); matchOrderTester = new MatchOrderTester(
exchangeWrapper,
erc20Wrapper,
erc721Wrapper,
erc1155ProxyWrapper,
devUtils,
);
tokenBalances = await matchOrderTester.getBalancesAsync(); tokenBalances = await matchOrderTester.getBalancesAsync();
}); });
beforeEach(async () => { beforeEach(async () => {
@ -338,8 +346,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(83, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(83, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -392,8 +400,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -443,8 +451,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(83, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(83, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(49, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -492,8 +500,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -537,8 +545,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(2126, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(2126, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1063, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1063, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -1162,7 +1170,7 @@ describe('matchOrders', () => {
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
feeRecipientAddress: makerAddressLeft, feeRecipientAddress: makerAddressLeft,
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
@ -1259,7 +1267,7 @@ describe('matchOrders', () => {
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18),
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 18),
}); });
@ -1286,7 +1294,7 @@ describe('matchOrders', () => {
it('should revert if the right maker asset is not equal to the left taker asset', async () => { it('should revert if the right maker asset is not equal to the left taker asset', async () => {
// Create orders to match // Create orders to match
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18),
}); });
@ -1440,8 +1448,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(87, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(87, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(48, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(48, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -1528,8 +1536,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -1579,8 +1587,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(87, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(87, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(48, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(48, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -1625,8 +1633,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -1670,8 +1678,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(89, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -1789,8 +1797,8 @@ describe('matchOrders', () => {
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(2126, 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(2126, 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1063, 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(1063, 0),
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
@ -2243,7 +2251,7 @@ describe('matchOrders', () => {
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
feeRecipientAddress: makerAddressLeft, feeRecipientAddress: makerAddressLeft,
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
@ -2340,7 +2348,7 @@ describe('matchOrders', () => {
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18),
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(2, 18),
}); });
@ -2367,7 +2375,7 @@ describe('matchOrders', () => {
it('should revert if the right maker asset is not equal to the left taker asset', async () => { it('should revert if the right maker asset is not equal to the left taker asset', async () => {
// Create orders to match // Create orders to match
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(10, 18),
}); });
@ -2675,11 +2683,11 @@ describe('matchOrders', () => {
let nameToERC1155NonFungibleAsset: { [name: string]: [string, BigNumber] }; let nameToERC1155NonFungibleAsset: { [name: string]: [string, BigNumber] };
let nameToMultiAssetAsset: { [name: string]: [BigNumber[], string[]] }; let nameToMultiAssetAsset: { [name: string]: [BigNumber[], string[]] };
function getAssetData(assetType: AssetType): string { async function getAssetDataAsync(assetType: AssetType): Promise<string> {
const encodeERC20AssetData = assetDataUtils.encodeERC20AssetData; const encodeERC20AssetData = await devUtils.encodeERC20AssetData.callAsync;
const encodeERC721AssetData = assetDataUtils.encodeERC721AssetData; const encodeERC721AssetData = await devUtils.encodeERC721AssetData.callAsync;
const encodeERC1155AssetData = assetDataUtils.encodeERC1155AssetData; const encodeERC1155AssetData = await devUtils.encodeERC1155AssetData.callAsync;
const encodeMultiAssetData = assetDataUtils.encodeMultiAssetData; const encodeMultiAssetData = await devUtils.encodeMultiAssetData.callAsync;
if (nameToERC20Asset[assetType] !== undefined) { if (nameToERC20Asset[assetType] !== undefined) {
const tokenAddress = nameToERC20Asset[assetType]; const tokenAddress = nameToERC20Asset[assetType];
return encodeERC20AssetData(tokenAddress); return encodeERC20AssetData(tokenAddress);
@ -2744,8 +2752,8 @@ describe('matchOrders', () => {
MULTI_ASSET_A: [ MULTI_ASSET_A: [
[ONE, TWO], [ONE, TWO],
[ [
assetDataUtils.encodeERC20AssetData(erc20Tokens[0].address), await devUtils.encodeERC20AssetData.callAsync(erc20Tokens[0].address),
assetDataUtils.encodeERC1155AssetData( await devUtils.encodeERC1155AssetData.callAsync(
defaultERC1155AssetAddress, defaultERC1155AssetAddress,
[erc1155FungibleTokens[0]], [erc1155FungibleTokens[0]],
[ONE], [ONE],
@ -2756,8 +2764,8 @@ describe('matchOrders', () => {
MULTI_ASSET_B: [ MULTI_ASSET_B: [
[ONE, TWO], [ONE, TWO],
[ [
assetDataUtils.encodeERC20AssetData(erc20Tokens[1].address), await devUtils.encodeERC20AssetData.callAsync(erc20Tokens[1].address),
assetDataUtils.encodeERC1155AssetData( await devUtils.encodeERC1155AssetData.callAsync(
defaultERC1155AssetAddress, defaultERC1155AssetAddress,
[erc1155FungibleTokens[1]], [erc1155FungibleTokens[1]],
[ONE], [ONE],
@ -2768,8 +2776,8 @@ describe('matchOrders', () => {
MULTI_ASSET_C: [ MULTI_ASSET_C: [
[ONE, TWO], [ONE, TWO],
[ [
assetDataUtils.encodeERC20AssetData(erc20Tokens[2].address), await devUtils.encodeERC20AssetData.callAsync(erc20Tokens[2].address),
assetDataUtils.encodeERC1155AssetData( await devUtils.encodeERC1155AssetData.callAsync(
defaultERC1155AssetAddress, defaultERC1155AssetAddress,
[erc1155FungibleTokens[2]], [erc1155FungibleTokens[2]],
[ONE], [ONE],
@ -2780,8 +2788,8 @@ describe('matchOrders', () => {
MULTI_ASSET_D: [ MULTI_ASSET_D: [
[ONE, TWO], [ONE, TWO],
[ [
assetDataUtils.encodeERC20AssetData(erc20Tokens[3].address), await devUtils.encodeERC20AssetData.callAsync(erc20Tokens[3].address),
assetDataUtils.encodeERC1155AssetData( await devUtils.encodeERC1155AssetData.callAsync(
erc1155Token.address, erc1155Token.address,
[erc1155FungibleTokens[3]], [erc1155FungibleTokens[3]],
[ONE], [ONE],
@ -2825,20 +2833,20 @@ describe('matchOrders', () => {
? leftMakerAssetAmount.minus(rightTakerAssetAmount) ? leftMakerAssetAmount.minus(rightTakerAssetAmount)
: Web3Wrapper.toBaseUnitAmount(0, 0); : Web3Wrapper.toBaseUnitAmount(0, 0);
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAssetData: getAssetData(combo.leftMaker), makerAssetData: await getAssetDataAsync(combo.leftMaker),
takerAssetData: getAssetData(combo.rightMaker), takerAssetData: await getAssetDataAsync(combo.rightMaker),
makerFeeAssetData: getAssetData(combo.leftMakerFee), makerFeeAssetData: await getAssetDataAsync(combo.leftMakerFee),
takerFeeAssetData: getAssetData(combo.leftTakerFee), takerFeeAssetData: await getAssetDataAsync(combo.leftTakerFee),
makerAssetAmount: leftMakerAssetAmount, makerAssetAmount: leftMakerAssetAmount,
takerAssetAmount: leftTakerAssetAmount, takerAssetAmount: leftTakerAssetAmount,
makerFee: leftMakerFeeAssetAmount, makerFee: leftMakerFeeAssetAmount,
takerFee: leftTakerFeeAssetAmount, takerFee: leftTakerFeeAssetAmount,
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAssetData: getAssetData(combo.rightMaker), makerAssetData: await getAssetDataAsync(combo.rightMaker),
takerAssetData: getAssetData(combo.leftMaker), takerAssetData: await getAssetDataAsync(combo.leftMaker),
makerFeeAssetData: getAssetData(combo.rightMakerFee), makerFeeAssetData: await getAssetDataAsync(combo.rightMakerFee),
takerFeeAssetData: getAssetData(combo.rightTakerFee), takerFeeAssetData: await getAssetDataAsync(combo.rightTakerFee),
makerAssetAmount: rightMakerAssetAmount, makerAssetAmount: rightMakerAssetAmount,
takerAssetAmount: rightTakerAssetAmount, takerAssetAmount: rightTakerAssetAmount,
makerFee: rightMakerFeeAssetAmount, makerFee: rightMakerFeeAssetAmount,
@ -2911,20 +2919,20 @@ describe('matchOrders', () => {
? rightMakerAssetAmount.minus(leftTakerAssetAmount) ? rightMakerAssetAmount.minus(leftTakerAssetAmount)
: Web3Wrapper.toBaseUnitAmount(0, 0); : Web3Wrapper.toBaseUnitAmount(0, 0);
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({ const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
makerAssetData: getAssetData(combo.leftMaker), makerAssetData: await getAssetDataAsync(combo.leftMaker),
takerAssetData: getAssetData(combo.rightMaker), takerAssetData: await getAssetDataAsync(combo.rightMaker),
makerFeeAssetData: getAssetData(combo.leftMakerFee), makerFeeAssetData: await getAssetDataAsync(combo.leftMakerFee),
takerFeeAssetData: getAssetData(combo.leftTakerFee), takerFeeAssetData: await getAssetDataAsync(combo.leftTakerFee),
makerAssetAmount: leftMakerAssetAmount, makerAssetAmount: leftMakerAssetAmount,
takerAssetAmount: leftTakerAssetAmount, takerAssetAmount: leftTakerAssetAmount,
makerFee: leftMakerFeeAssetAmount, makerFee: leftMakerFeeAssetAmount,
takerFee: leftTakerFeeAssetAmount, takerFee: leftTakerFeeAssetAmount,
}); });
const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({ const signedOrderRight = await orderFactoryRight.newSignedOrderAsync({
makerAssetData: getAssetData(combo.rightMaker), makerAssetData: await getAssetDataAsync(combo.rightMaker),
takerAssetData: getAssetData(combo.leftMaker), takerAssetData: await getAssetDataAsync(combo.leftMaker),
makerFeeAssetData: getAssetData(combo.rightMakerFee), makerFeeAssetData: await getAssetDataAsync(combo.rightMakerFee),
takerFeeAssetData: getAssetData(combo.rightTakerFee), takerFeeAssetData: await getAssetDataAsync(combo.rightTakerFee),
makerAssetAmount: rightMakerAssetAmount, makerAssetAmount: rightMakerAssetAmount,
takerAssetAmount: rightTakerAssetAmount, takerAssetAmount: rightTakerAssetAmount,
makerFee: rightMakerFeeAssetAmount, makerFee: rightMakerFeeAssetAmount,

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { import {
blockchainTests, blockchainTests,
constants, constants,
@ -10,13 +11,7 @@ import {
randomAddress, randomAddress,
TransactionFactory, TransactionFactory,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { import { ExchangeRevertErrors, orderHashUtils, transactionHashUtils } from '@0x/order-utils';
assetDataUtils,
ExchangeRevertErrors,
orderHashUtils,
signatureUtils,
transactionHashUtils,
} from '@0x/order-utils';
import { SignatureType, SignedOrder, SignedZeroExTransaction } from '@0x/types'; import { SignatureType, SignedOrder, SignedZeroExTransaction } from '@0x/types';
import { BigNumber, StringRevertError } from '@0x/utils'; import { BigNumber, StringRevertError } from '@0x/utils';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
@ -42,6 +37,7 @@ blockchainTests.resets('MixinSignatureValidator', env => {
let signerPrivateKey: Buffer; let signerPrivateKey: Buffer;
let notSignerAddress: string; let notSignerAddress: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, env.provider, env.txDefaults);
const eip1271Data = new IEIP1271DataContract(constants.NULL_ADDRESS, env.provider, env.txDefaults); const eip1271Data = new IEIP1271DataContract(constants.NULL_ADDRESS, env.provider, env.txDefaults);
before(async () => { before(async () => {
chainId = await env.getChainIdAsync(); chainId = await env.getChainIdAsync();
@ -174,7 +170,9 @@ blockchainTests.resets('MixinSignatureValidator', env => {
it('should return true when SignatureType=EthSign and signature is valid', async () => { it('should return true when SignatureType=EthSign and signature is valid', async () => {
// Create EthSign signature // Create EthSign signature
const hashHex = getCurrentHashHex(); const hashHex = getCurrentHashHex();
const orderHashWithEthSignPrefixHex = signatureUtils.addSignedMessagePrefix(hashHex); const orderHashWithEthSignPrefixHex = ethUtil.bufferToHex(
ethUtil.hashPersonalMessage(ethUtil.toBuffer(hashHex)),
);
const signatureHex = hexConcat( const signatureHex = hexConcat(
signDataHex(orderHashWithEthSignPrefixHex, signerPrivateKey), signDataHex(orderHashWithEthSignPrefixHex, signerPrivateKey),
SignatureType.EthSign, SignatureType.EthSign,
@ -429,10 +427,10 @@ blockchainTests.resets('MixinSignatureValidator', env => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress, makerAddress,
feeRecipientAddress: randomAddress(), feeRecipientAddress: randomAddress(),
makerAssetData: assetDataUtils.encodeERC20AssetData(randomAddress()), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(randomAddress()),
takerAssetData: assetDataUtils.encodeERC20AssetData(randomAddress()), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(randomAddress()),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(randomAddress()), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(randomAddress()),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(randomAddress()), takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(randomAddress()),
makerFee: constants.ZERO_AMOUNT, makerFee: constants.ZERO_AMOUNT,
takerFee: constants.ZERO_AMOUNT, takerFee: constants.ZERO_AMOUNT,
exchangeAddress: signatureValidator.address, exchangeAddress: signatureValidator.address,

View File

@ -1,5 +1,6 @@
// tslint:disable: max-file-line-count // tslint:disable: max-file-line-count
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20'; import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
import { import {
blockchainTests, blockchainTests,
@ -10,7 +11,7 @@ import {
OrderFactory, OrderFactory,
TransactionFactory, TransactionFactory,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { assetDataUtils, ExchangeRevertErrors, orderHashUtils, transactionHashUtils } from '@0x/order-utils'; import { ExchangeRevertErrors, orderHashUtils, transactionHashUtils } from '@0x/order-utils';
import { FillResults, OrderStatus } from '@0x/types'; import { FillResults, OrderStatus } from '@0x/types';
import { AbiEncoder, BigNumber } from '@0x/utils'; import { AbiEncoder, BigNumber } from '@0x/utils';
import { LogWithDecodedArgs, MethodAbi } from 'ethereum-types'; import { LogWithDecodedArgs, MethodAbi } from 'ethereum-types';
@ -66,6 +67,7 @@ blockchainTests.resets('Exchange transactions', env => {
let takerPrivateKey: Buffer; let takerPrivateKey: Buffer;
let taker2PrivateKey: Buffer; let taker2PrivateKey: Buffer;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, env.provider, env.txDefaults);
before(async () => { before(async () => {
chainId = await env.getChainIdAsync(); chainId = await env.getChainIdAsync();
const accounts = await env.getAccountAddressesAsync(); const accounts = await env.getAccountAddressesAsync();
@ -110,10 +112,10 @@ blockchainTests.resets('Exchange transactions', env => {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress, makerAddress,
feeRecipientAddress, feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerTokenAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultMakerTokenAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerTokenAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerTokenAddress),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerFeeTokenAddress), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultMakerFeeTokenAddress),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerFeeTokenAddress), takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerFeeTokenAddress),
exchangeAddress: exchangeInstance.address, exchangeAddress: exchangeInstance.address,
chainId, chainId,
}; };

View File

@ -1,10 +1,10 @@
import { AbstractAssetWrapper, constants } from '@0x/contracts-test-utils'; import { AbstractAssetWrapper, constants } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId } from '@0x/types'; import { AssetProxyId } from '@0x/types';
import { BigNumber, errorUtils } from '@0x/utils'; import { BigNumber, errorUtils } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy'; import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
interface ProxyIdToAssetWrappers { interface ProxyIdToAssetWrappers {
[proxyId: string]: AbstractAssetWrapper; [proxyId: string]: AbstractAssetWrapper;
@ -19,17 +19,20 @@ const ZERO_NFT_UNIT = new BigNumber(0);
*/ */
export class AssetWrapper { export class AssetWrapper {
private readonly _proxyIdToAssetWrappers: ProxyIdToAssetWrappers; private readonly _proxyIdToAssetWrappers: ProxyIdToAssetWrappers;
private readonly _burnerAddress: string;
constructor(assetWrappers: AbstractAssetWrapper[], burnerAddress: string) { constructor(
assetWrappers: AbstractAssetWrapper[],
private readonly _burnerAddress: string,
private readonly _devUtils: DevUtilsContract,
) {
this._proxyIdToAssetWrappers = {}; this._proxyIdToAssetWrappers = {};
this._burnerAddress = burnerAddress;
_.each(assetWrappers, assetWrapper => { _.each(assetWrappers, assetWrapper => {
const proxyId = assetWrapper.getProxyId(); const proxyId = assetWrapper.getProxyId();
this._proxyIdToAssetWrappers[proxyId] = assetWrapper; this._proxyIdToAssetWrappers[proxyId] = assetWrapper;
}); });
} }
public async getBalanceAsync(userAddress: string, assetData: string): Promise<BigNumber> { public async getBalanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const proxyId = assetDataUtils.decodeAssetProxyId(assetData); const proxyId = await this._devUtils.decodeAssetProxyId.callAsync(assetData);
switch (proxyId) { switch (proxyId) {
case AssetProxyId.ERC20: { case AssetProxyId.ERC20: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
@ -40,33 +43,38 @@ export class AssetWrapper {
case AssetProxyId.ERC721: { case AssetProxyId.ERC721: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const assetWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper; const assetWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
const assetProxyData = assetDataUtils.decodeERC721AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const isOwner = await assetWrapper.isOwnerAsync( const [assetProxyId, tokenAddress, tokenId] = await this._devUtils.decodeERC721AssetData.callAsync(
userAddress, assetData,
assetProxyData.tokenAddress,
assetProxyData.tokenId,
); );
const isOwner = await assetWrapper.isOwnerAsync(userAddress, tokenAddress, tokenId);
const balance = isOwner ? ONE_NFT_UNIT : ZERO_NFT_UNIT; const balance = isOwner ? ONE_NFT_UNIT : ZERO_NFT_UNIT;
return balance; return balance;
} }
case AssetProxyId.ERC1155: { case AssetProxyId.ERC1155: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper; const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
const assetProxyData = assetDataUtils.decodeERC1155AssetData(assetData); const [
const assetWrapper = assetProxyWrapper.getContractWrapper(assetProxyData.tokenAddress); // tslint:disable-next-line:no-unused-variable
assetProxyAddress,
tokenAddress,
tokenIds,
] = await this._devUtils.decodeERC1155AssetData.callAsync(assetData);
const assetWrapper = assetProxyWrapper.getContractWrapper(tokenAddress);
const balances = await Promise.all( const balances = await Promise.all(
_.map(assetProxyData.tokenIds).map(tokenId => assetWrapper.getBalanceAsync(userAddress, tokenId)), _.map(tokenIds).map(tokenId => assetWrapper.getBalanceAsync(userAddress, tokenId)),
); );
return BigNumber.min(...balances); return BigNumber.min(...balances);
} }
case AssetProxyId.MultiAsset: { case AssetProxyId.MultiAsset: {
const assetProxyData = assetDataUtils.decodeMultiAssetData(assetData); // tslint:disable-next-line:no-unused-variable
const nestedBalances = await Promise.all( const [assetProxyId, amounts, nestedAssetData] = await this._devUtils.decodeMultiAssetData.callAsync(
assetProxyData.nestedAssetData.map(async nestedAssetData => assetData,
this.getBalanceAsync(userAddress, nestedAssetData),
),
); );
const scaledBalances = _.zip(assetProxyData.amounts, nestedBalances).map(([amount, balance]) => const nestedBalances = await Promise.all(
nestedAssetData.map(async _nestedAssetData => this.getBalanceAsync(userAddress, _nestedAssetData)),
);
const scaledBalances = _.zip(amounts, nestedBalances).map(([amount, balance]) =>
(balance as BigNumber).div(amount as BigNumber).integerValue(BigNumber.ROUND_HALF_UP), (balance as BigNumber).div(amount as BigNumber).integerValue(BigNumber.ROUND_HALF_UP),
); );
return BigNumber.min(...scaledBalances); return BigNumber.min(...scaledBalances);
@ -76,7 +84,7 @@ export class AssetWrapper {
} }
} }
public async setBalanceAsync(userAddress: string, assetData: string, desiredBalance: BigNumber): Promise<void> { public async setBalanceAsync(userAddress: string, assetData: string, desiredBalance: BigNumber): Promise<void> {
const proxyId = assetDataUtils.decodeAssetProxyId(assetData); const proxyId = await this._devUtils.decodeAssetProxyId.callAsync(assetData);
switch (proxyId) { switch (proxyId) {
case AssetProxyId.ERC20: { case AssetProxyId.ERC20: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
@ -91,36 +99,23 @@ export class AssetWrapper {
case AssetProxyId.ERC721: { case AssetProxyId.ERC721: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper; const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
const assetProxyData = assetDataUtils.decodeERC721AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const doesTokenExist = erc721Wrapper.doesTokenExistAsync( const [assetProxyId, tokenAddress, tokenId] = await this._devUtils.decodeERC721AssetData.callAsync(
assetProxyData.tokenAddress, assetData,
assetProxyData.tokenId,
); );
const doesTokenExist = erc721Wrapper.doesTokenExistAsync(tokenAddress, tokenId);
if (!doesTokenExist && desiredBalance.gte(1)) { if (!doesTokenExist && desiredBalance.gte(1)) {
await erc721Wrapper.mintAsync(assetProxyData.tokenAddress, assetProxyData.tokenId, userAddress); await erc721Wrapper.mintAsync(tokenAddress, tokenId, userAddress);
return; return;
} else if (!doesTokenExist && desiredBalance.lt(1)) { } else if (!doesTokenExist && desiredBalance.lt(1)) {
return; // noop return; // noop
} }
const tokenOwner = await erc721Wrapper.ownerOfAsync( const tokenOwner = await erc721Wrapper.ownerOfAsync(tokenAddress, tokenId);
assetProxyData.tokenAddress,
assetProxyData.tokenId,
);
if (userAddress !== tokenOwner && desiredBalance.gte(1)) { if (userAddress !== tokenOwner && desiredBalance.gte(1)) {
await erc721Wrapper.transferFromAsync( await erc721Wrapper.transferFromAsync(tokenAddress, tokenId, tokenOwner, userAddress);
assetProxyData.tokenAddress,
assetProxyData.tokenId,
tokenOwner,
userAddress,
);
} else if (tokenOwner === userAddress && desiredBalance.lt(1)) { } else if (tokenOwner === userAddress && desiredBalance.lt(1)) {
// Burn token // Burn token
await erc721Wrapper.transferFromAsync( await erc721Wrapper.transferFromAsync(tokenAddress, tokenId, tokenOwner, this._burnerAddress);
assetProxyData.tokenAddress,
assetProxyData.tokenId,
tokenOwner,
this._burnerAddress,
);
return; return;
} else if ( } else if (
(userAddress !== tokenOwner && desiredBalance.lt(1)) || (userAddress !== tokenOwner && desiredBalance.lt(1)) ||
@ -133,15 +128,21 @@ export class AssetWrapper {
case AssetProxyId.ERC1155: { case AssetProxyId.ERC1155: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper; const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
const assetProxyData = assetDataUtils.decodeERC1155AssetData(assetData); const [
const assetWrapper = assetProxyWrapper.getContractWrapper(assetProxyData.tokenAddress); // tslint:disable-next-line:no-unused-variable
const tokenValuesSum = BigNumber.sum(...assetProxyData.tokenValues); assetProxyAddress,
let tokenValueRatios = assetProxyData.tokenValues; tokenAddress,
tokenIds,
tokenValues,
] = await this._devUtils.decodeERC1155AssetData.callAsync(assetData);
const assetWrapper = assetProxyWrapper.getContractWrapper(tokenAddress);
const tokenValuesSum = BigNumber.sum(...tokenValues);
let tokenValueRatios = tokenValues;
if (!tokenValuesSum.eq(0)) { if (!tokenValuesSum.eq(0)) {
tokenValueRatios = assetProxyData.tokenValues.map(v => v.div(tokenValuesSum)); tokenValueRatios = tokenValues.map(v => v.div(tokenValuesSum));
} }
for (const i of _.times(assetProxyData.tokenIds.length)) { for (const i of _.times(tokenIds.length)) {
const tokenId = assetProxyData.tokenIds[i]; const tokenId = tokenIds[i];
const tokenValueRatio = tokenValueRatios[i]; const tokenValueRatio = tokenValueRatios[i];
const scaledDesiredBalance = desiredBalance.times(tokenValueRatio); const scaledDesiredBalance = desiredBalance.times(tokenValueRatio);
const isFungible = await assetWrapper.isFungibleItemAsync(tokenId); const isFungible = await assetWrapper.isFungibleItemAsync(tokenId);
@ -195,16 +196,18 @@ export class AssetWrapper {
break; break;
} }
case AssetProxyId.MultiAsset: { case AssetProxyId.MultiAsset: {
const assetProxyData = assetDataUtils.decodeMultiAssetData(assetData); // tslint:disable-next-line:no-unused-variable
const amountsSum = BigNumber.sum(...assetProxyData.amounts); const [assetProxyId, amounts, nestedAssetData] = await this._devUtils.decodeMultiAssetData.callAsync(
let assetAmountRatios = assetProxyData.amounts; assetData,
);
const amountsSum = BigNumber.sum(...amounts);
let assetAmountRatios = amounts;
if (!amountsSum.eq(0)) { if (!amountsSum.eq(0)) {
assetAmountRatios = assetProxyData.amounts.map(amt => amt.div(amountsSum)); assetAmountRatios = amounts.map(amt => amt.div(amountsSum));
} }
for (const i of _.times(assetProxyData.amounts.length)) { for (const i of _.times(amounts.length)) {
const nestedAssetData = assetProxyData.nestedAssetData[i];
const assetAmountRatio = assetAmountRatios[i]; const assetAmountRatio = assetAmountRatios[i];
await this.setBalanceAsync(userAddress, nestedAssetData, desiredBalance.times(assetAmountRatio)); await this.setBalanceAsync(userAddress, nestedAssetData[i], desiredBalance.times(assetAmountRatio));
} }
break; break;
} }
@ -217,7 +220,7 @@ export class AssetWrapper {
assetData: string, assetData: string,
desiredBalance: BigNumber, desiredBalance: BigNumber,
): Promise<void> { ): Promise<void> {
const proxyId = assetDataUtils.decodeAssetProxyId(assetData); const proxyId = await this._devUtils.decodeAssetProxyId.callAsync(assetData);
switch (proxyId) { switch (proxyId) {
case AssetProxyId.ERC20: case AssetProxyId.ERC20:
case AssetProxyId.ERC721: case AssetProxyId.ERC721:
@ -232,7 +235,7 @@ export class AssetWrapper {
} }
} }
public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise<BigNumber> { public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const proxyId = assetDataUtils.decodeAssetProxyId(assetData); const proxyId = await this._devUtils.decodeAssetProxyId.callAsync(assetData);
switch (proxyId) { switch (proxyId) {
case AssetProxyId.ERC20: { case AssetProxyId.ERC20: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
@ -243,30 +246,27 @@ export class AssetWrapper {
case AssetProxyId.ERC721: { case AssetProxyId.ERC721: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const assetWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper; const assetWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
const erc721ProxyData = assetDataUtils.decodeERC721AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const isProxyApprovedForAll = await assetWrapper.isProxyApprovedForAllAsync( const [assetProxyId, tokenAddress, tokenId] = await this._devUtils.decodeERC721AssetData.callAsync(
userAddress, assetData,
erc721ProxyData.tokenAddress,
); );
const isProxyApprovedForAll = await assetWrapper.isProxyApprovedForAllAsync(userAddress, tokenAddress);
if (isProxyApprovedForAll) { if (isProxyApprovedForAll) {
return constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; return constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
} }
const isProxyApproved = await assetWrapper.isProxyApprovedAsync( const isProxyApproved = await assetWrapper.isProxyApprovedAsync(tokenAddress, tokenId);
erc721ProxyData.tokenAddress,
erc721ProxyData.tokenId,
);
const allowance = isProxyApproved ? ONE_NFT_UNIT : ZERO_NFT_UNIT; const allowance = isProxyApproved ? ONE_NFT_UNIT : ZERO_NFT_UNIT;
return allowance; return allowance;
} }
case AssetProxyId.ERC1155: { case AssetProxyId.ERC1155: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper; const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
const assetProxyData = assetDataUtils.decodeERC1155AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const isApprovedForAll = await assetProxyWrapper.isProxyApprovedForAllAsync( const [assetProxyAddress, tokenAddress] = await this._devUtils.decodeERC1155AssetData.callAsync(
userAddress, assetData,
assetProxyData.tokenAddress,
); );
const isApprovedForAll = await assetProxyWrapper.isProxyApprovedForAllAsync(userAddress, tokenAddress);
if (!isApprovedForAll) { if (!isApprovedForAll) {
// ERC1155 is all or nothing. // ERC1155 is all or nothing.
return constants.ZERO_AMOUNT; return constants.ZERO_AMOUNT;
@ -274,10 +274,13 @@ export class AssetWrapper {
return constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; return constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
} }
case AssetProxyId.MultiAsset: { case AssetProxyId.MultiAsset: {
const assetProxyData = assetDataUtils.decodeMultiAssetData(assetData); // tslint:disable-next-line:no-unused-variable
const [assetProxyId, amounts, nestedAssetData] = await this._devUtils.decodeMultiAssetData.callAsync(
assetData,
);
const allowances = await Promise.all( const allowances = await Promise.all(
assetProxyData.nestedAssetData.map(async nestedAssetData => nestedAssetData.map(async _nestedAssetData =>
this.getProxyAllowanceAsync(userAddress, nestedAssetData), this.getProxyAllowanceAsync(userAddress, _nestedAssetData),
), ),
); );
return BigNumber.min(...allowances); return BigNumber.min(...allowances);
@ -291,7 +294,7 @@ export class AssetWrapper {
assetData: string, assetData: string,
desiredAllowance: BigNumber, desiredAllowance: BigNumber,
): Promise<void> { ): Promise<void> {
const proxyId = assetDataUtils.decodeAssetProxyId(assetData); const proxyId = await this._devUtils.decodeAssetProxyId.callAsync(assetData);
switch (proxyId) { switch (proxyId) {
case AssetProxyId.ERC20: { case AssetProxyId.ERC20: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
@ -311,46 +314,32 @@ export class AssetWrapper {
} }
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper; const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
const assetProxyData = assetDataUtils.decodeERC721AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const [assetProxyId, tokenAddress, tokenId] = await this._devUtils.decodeERC721AssetData.callAsync(
assetData,
);
const doesTokenExist = await erc721Wrapper.doesTokenExistAsync( const doesTokenExist = await erc721Wrapper.doesTokenExistAsync(tokenAddress, tokenId);
assetProxyData.tokenAddress,
assetProxyData.tokenId,
);
if (!doesTokenExist) { if (!doesTokenExist) {
throw new Error( throw new Error(`Cannot setProxyAllowance on non-existent token: ${tokenAddress} ${tokenId}`);
`Cannot setProxyAllowance on non-existent token: ${assetProxyData.tokenAddress} ${
assetProxyData.tokenId
}`,
);
} }
const isProxyApprovedForAll = await erc721Wrapper.isProxyApprovedForAllAsync( const isProxyApprovedForAll = await erc721Wrapper.isProxyApprovedForAllAsync(userAddress, tokenAddress);
userAddress,
assetProxyData.tokenAddress,
);
if (!isProxyApprovedForAll && desiredAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { if (!isProxyApprovedForAll && desiredAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
const isApproved = true; const isApproved = true;
await erc721Wrapper.approveProxyForAllAsync(assetProxyData.tokenAddress, userAddress, isApproved); await erc721Wrapper.approveProxyForAllAsync(tokenAddress, userAddress, isApproved);
} else if (isProxyApprovedForAll && desiredAllowance.eq(0)) { } else if (isProxyApprovedForAll && desiredAllowance.eq(0)) {
const isApproved = false; const isApproved = false;
await erc721Wrapper.approveProxyForAllAsync(assetProxyData.tokenAddress, userAddress, isApproved); await erc721Wrapper.approveProxyForAllAsync(tokenAddress, userAddress, isApproved);
} else if (isProxyApprovedForAll && desiredAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) { } else if (isProxyApprovedForAll && desiredAllowance.eq(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS)) {
return; // Noop return; // Noop
} }
const isProxyApproved = await erc721Wrapper.isProxyApprovedAsync( const isProxyApproved = await erc721Wrapper.isProxyApprovedAsync(tokenAddress, tokenId);
assetProxyData.tokenAddress,
assetProxyData.tokenId,
);
if (!isProxyApproved && desiredAllowance.eq(1)) { if (!isProxyApproved && desiredAllowance.eq(1)) {
await erc721Wrapper.approveProxyAsync(assetProxyData.tokenAddress, assetProxyData.tokenId); await erc721Wrapper.approveProxyAsync(tokenAddress, tokenId);
} else if (isProxyApproved && desiredAllowance.eq(0)) { } else if (isProxyApproved && desiredAllowance.eq(0)) {
// Remove approval // Remove approval
await erc721Wrapper.approveAsync( await erc721Wrapper.approveAsync(constants.NULL_ADDRESS, tokenAddress, tokenId);
constants.NULL_ADDRESS,
assetProxyData.tokenAddress,
assetProxyData.tokenId,
);
} else if ( } else if (
(!isProxyApproved && desiredAllowance.eq(0)) || (!isProxyApproved && desiredAllowance.eq(0)) ||
(isProxyApproved && desiredAllowance.eq(1)) (isProxyApproved && desiredAllowance.eq(1))
@ -362,7 +351,10 @@ export class AssetWrapper {
case AssetProxyId.ERC1155: { case AssetProxyId.ERC1155: {
// tslint:disable-next-line:no-unnecessary-type-assertion // tslint:disable-next-line:no-unnecessary-type-assertion
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper; const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
const assetProxyData = assetDataUtils.decodeERC1155AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const [assetProxyAddress, tokenAddress] = await this._devUtils.decodeERC1155AssetData.callAsync(
assetData,
);
// ERC1155 allowances are all or nothing. // ERC1155 allowances are all or nothing.
const shouldApprovedForAll = desiredAllowance.gt(0); const shouldApprovedForAll = desiredAllowance.gt(0);
const currentAllowance = await this.getProxyAllowanceAsync(userAddress, assetData); const currentAllowance = await this.getProxyAllowanceAsync(userAddress, assetData);
@ -371,19 +363,18 @@ export class AssetWrapper {
} else if (!shouldApprovedForAll && currentAllowance.eq(constants.ZERO_AMOUNT)) { } else if (!shouldApprovedForAll && currentAllowance.eq(constants.ZERO_AMOUNT)) {
// Nothing to do. // Nothing to do.
} else { } else {
assetProxyWrapper.setProxyAllowanceForAllAsync( assetProxyWrapper.setProxyAllowanceForAllAsync(userAddress, tokenAddress, shouldApprovedForAll);
userAddress,
assetProxyData.tokenAddress,
shouldApprovedForAll,
);
} }
break; break;
} }
case AssetProxyId.MultiAsset: { case AssetProxyId.MultiAsset: {
const assetProxyData = assetDataUtils.decodeMultiAssetData(assetData); // tslint:disable-next-line:no-unused-variable
const [assetProxyId, amounts, nestedAssetData] = await this._devUtils.decodeMultiAssetData.callAsync(
assetData,
);
await Promise.all( await Promise.all(
assetProxyData.nestedAssetData.map(async nestedAssetData => nestedAssetData.map(async _nestedAssetData =>
this.setProxyAllowanceAsync(userAddress, nestedAssetData, desiredAllowance), this.setProxyAllowanceAsync(userAddress, _nestedAssetData, desiredAllowance),
), ),
); );
break; break;

View File

@ -5,6 +5,7 @@ import {
ERC721Wrapper, ERC721Wrapper,
MultiAssetProxyContract, MultiAssetProxyContract,
} from '@0x/contracts-asset-proxy'; } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, expect, LogDecoder, orderUtils, signingUtils } from '@0x/contracts-test-utils'; import { constants, expect, LogDecoder, orderUtils, signingUtils } from '@0x/contracts-test-utils';
import { BalanceAndProxyAllowanceLazyStore, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils'; import { BalanceAndProxyAllowanceLazyStore, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
import { FillResults, Order, SignatureType, SignedOrder } from '@0x/types'; import { FillResults, Order, SignatureType, SignedOrder } from '@0x/types';
@ -106,7 +107,8 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
{}, {},
); );
const assetWrapper = new AssetWrapper([erc20Wrapper, erc721Wrapper, erc1155Wrapper], burnerAddress); const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
const assetWrapper = new AssetWrapper([erc20Wrapper, erc721Wrapper, erc1155Wrapper], burnerAddress, devUtils);
const exchangeContract = await ExchangeContract.deployFrom0xArtifactAsync( const exchangeContract = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange, artifacts.Exchange,
@ -156,6 +158,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc1155Proxy.address, { from: ownerAddress }); await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc1155Proxy.address, { from: ownerAddress });
const orderFactory = new OrderFactoryFromScenario( const orderFactory = new OrderFactoryFromScenario(
devUtils,
userAddresses, userAddresses,
erc20EighteenDecimalTokens.map(token => token.address), erc20EighteenDecimalTokens.map(token => token.address),
erc20FiveDecimalTokens.map(token => token.address), erc20FiveDecimalTokens.map(token => token.address),
@ -457,7 +460,7 @@ export class FillOrderCombinatorialUtils {
fillErrorIfExists?: FillOrderError, fillErrorIfExists?: FillOrderError,
): Promise<void> { ): Promise<void> {
const lazyStore = new BalanceAndProxyAllowanceLazyStore(this.balanceAndProxyAllowanceFetcher); const lazyStore = new BalanceAndProxyAllowanceLazyStore(this.balanceAndProxyAllowanceFetcher);
const signedOrder = await this._generateSignedOrder(fillScenario.orderScenario); const signedOrder = await this._generateSignedOrderAsync(fillScenario.orderScenario);
const takerAssetFillAmount = getTakerAssetFillAmount(signedOrder, fillScenario); const takerAssetFillAmount = getTakerAssetFillAmount(signedOrder, fillScenario);
await this._modifyTraderStateAsync(fillScenario, signedOrder, takerAssetFillAmount); await this._modifyTraderStateAsync(fillScenario, signedOrder, takerAssetFillAmount);
@ -484,8 +487,8 @@ export class FillOrderCombinatorialUtils {
); );
} }
private _generateSignedOrder(orderScenario: OrderScenario): SignedOrder { private async _generateSignedOrderAsync(orderScenario: OrderScenario): Promise<SignedOrder> {
const order = this.orderFactory.generateOrder(orderScenario); const order = await this.orderFactory.generateOrderAsync(orderScenario);
const orderHashBuff = orderHashUtils.getOrderHashBuffer(order); const orderHashBuff = orderHashUtils.getOrderHashBuffer(order);
const signature = signingUtils.signMessage(orderHashBuff, this.makerPrivateKey, SignatureType.EthSign); const signature = signingUtils.signMessage(orderHashBuff, this.makerPrivateKey, SignatureType.EthSign);
const signedOrder = { const signedOrder = {

View File

@ -1,6 +1,7 @@
import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy'; import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, ERC1155HoldingsByOwner, expect, OrderStatus } from '@0x/contracts-test-utils'; import { constants, ERC1155HoldingsByOwner, expect, OrderStatus } from '@0x/contracts-test-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { orderHashUtils } from '@0x/order-utils';
import { AssetProxyId, BatchMatchedFillResults, FillResults, MatchedFillResults, SignedOrder } from '@0x/types'; import { AssetProxyId, BatchMatchedFillResults, FillResults, MatchedFillResults, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -111,14 +112,6 @@ export type MatchOrdersAsyncCall = (
) => Promise<TransactionReceiptWithDecodedLogs>; ) => Promise<TransactionReceiptWithDecodedLogs>;
export class MatchOrderTester { export class MatchOrderTester {
public exchangeWrapper: ExchangeWrapper;
public erc20Wrapper: ERC20Wrapper;
public erc721Wrapper: ERC721Wrapper;
public erc1155ProxyWrapper: ERC1155ProxyWrapper;
public batchMatchOrdersCallAsync?: BatchMatchOrdersAsyncCall;
public batchMatchOrdersWithMaximalFillCallAsync?: BatchMatchOrdersAsyncCall;
public matchOrdersCallAsync?: MatchOrdersAsyncCall;
public matchOrdersWithMaximalFillCallAsync?: MatchOrdersAsyncCall;
private readonly _initialTokenBalancesPromise: Promise<TokenBalances>; private readonly _initialTokenBalancesPromise: Promise<TokenBalances>;
/** /**
@ -137,23 +130,16 @@ export class MatchOrderTester {
* `ExchangeWrapper.matchOrdersAsync()`. * `ExchangeWrapper.matchOrdersAsync()`.
*/ */
constructor( constructor(
exchangeWrapper: ExchangeWrapper, public exchangeWrapper: ExchangeWrapper,
erc20Wrapper: ERC20Wrapper, public erc20Wrapper: ERC20Wrapper,
erc721Wrapper: ERC721Wrapper, public erc721Wrapper: ERC721Wrapper,
erc1155ProxyWrapper: ERC1155ProxyWrapper, public erc1155ProxyWrapper: ERC1155ProxyWrapper,
batchMatchOrdersCallAsync?: BatchMatchOrdersAsyncCall, protected _devUtils: DevUtilsContract,
batchMatchOrdersWithMaximalFillCallAsync?: BatchMatchOrdersAsyncCall, public batchMatchOrdersCallAsync?: BatchMatchOrdersAsyncCall,
matchOrdersCallAsync?: MatchOrdersAsyncCall, public batchMatchOrdersWithMaximalFillCallAsync?: BatchMatchOrdersAsyncCall,
matchOrdersWithMaximalFillCallAsync?: MatchOrdersAsyncCall, public matchOrdersCallAsync?: MatchOrdersAsyncCall,
public matchOrdersWithMaximalFillCallAsync?: MatchOrdersAsyncCall,
) { ) {
this.exchangeWrapper = exchangeWrapper;
this.erc20Wrapper = erc20Wrapper;
this.erc721Wrapper = erc721Wrapper;
this.erc1155ProxyWrapper = erc1155ProxyWrapper;
this.batchMatchOrdersCallAsync = batchMatchOrdersCallAsync;
this.batchMatchOrdersWithMaximalFillCallAsync = batchMatchOrdersWithMaximalFillCallAsync;
this.matchOrdersCallAsync = matchOrdersCallAsync;
this.matchOrdersWithMaximalFillCallAsync = matchOrdersWithMaximalFillCallAsync;
this._initialTokenBalancesPromise = this.getBalancesAsync(); this._initialTokenBalancesPromise = this.getBalancesAsync();
} }
@ -215,12 +201,13 @@ export class MatchOrderTester {
); );
} }
// Simulate the batch order match. // Simulate the batch order match.
const expectedBatchMatchResults = simulateBatchMatchOrders( const expectedBatchMatchResults = await simulateBatchMatchOrdersAsync(
orders, orders,
takerAddress, takerAddress,
_initialTokenBalances, _initialTokenBalances,
matchPairs, matchPairs,
expectedTransferAmounts, expectedTransferAmounts,
this._devUtils,
); );
const expectedResults = convertToBatchMatchResults(expectedBatchMatchResults); const expectedResults = convertToBatchMatchResults(expectedBatchMatchResults);
expect(actualBatchMatchResults).to.be.eql(expectedResults); expect(actualBatchMatchResults).to.be.eql(expectedResults);
@ -282,11 +269,12 @@ export class MatchOrderTester {
transactionReceipt = await this._executeMatchOrdersAsync(orders.leftOrder, orders.rightOrder, takerAddress); transactionReceipt = await this._executeMatchOrdersAsync(orders.leftOrder, orders.rightOrder, takerAddress);
} }
// Simulate the fill. // Simulate the fill.
const expectedMatchResults = simulateMatchOrders( const expectedMatchResults = await simulateMatchOrdersAsync(
orders, orders,
takerAddress, takerAddress,
_initialTokenBalances, _initialTokenBalances,
toFullMatchTransferAmounts(expectedTransferAmounts), toFullMatchTransferAmounts(expectedTransferAmounts),
this._devUtils,
); );
const expectedResults = convertToMatchResults(expectedMatchResults); const expectedResults = convertToMatchResults(expectedMatchResults);
expect(actualMatchResults).to.be.eql(expectedResults); expect(actualMatchResults).to.be.eql(expectedResults);
@ -403,13 +391,14 @@ function toFullMatchTransferAmounts(partial: Partial<MatchTransferAmounts>): Mat
* @param transferAmounts Amounts to transfer during the simulation. * @param transferAmounts Amounts to transfer during the simulation.
* @return The new account balances and fill events that occurred during the match. * @return The new account balances and fill events that occurred during the match.
*/ */
function simulateBatchMatchOrders( async function simulateBatchMatchOrdersAsync(
orders: BatchMatchedOrders, orders: BatchMatchedOrders,
takerAddress: string, takerAddress: string,
tokenBalances: TokenBalances, tokenBalances: TokenBalances,
matchPairs: Array<[number, number]>, matchPairs: Array<[number, number]>,
transferAmounts: Array<Partial<MatchTransferAmounts>>, transferAmounts: Array<Partial<MatchTransferAmounts>>,
): BatchMatchResults { devUtils: DevUtilsContract,
): Promise<BatchMatchResults> {
// Initialize variables // Initialize variables
let leftIdx = 0; let leftIdx = 0;
let rightIdx = 0; let rightIdx = 0;
@ -465,11 +454,12 @@ function simulateBatchMatchOrders(
// Add the latest match to the batch match results // Add the latest match to the batch match results
batchMatchResults.matches.push( batchMatchResults.matches.push(
simulateMatchOrders( await simulateMatchOrdersAsync(
matchedOrders, matchedOrders,
takerAddress, takerAddress,
tokenBalances, tokenBalances,
toFullMatchTransferAmounts(transferAmounts[i]), toFullMatchTransferAmounts(transferAmounts[i]),
devUtils,
), ),
); );
@ -525,12 +515,13 @@ function simulateBatchMatchOrders(
* @param transferAmounts Amounts to transfer during the simulation. * @param transferAmounts Amounts to transfer during the simulation.
* @return The new account balances and fill events that occurred during the match. * @return The new account balances and fill events that occurred during the match.
*/ */
function simulateMatchOrders( async function simulateMatchOrdersAsync(
orders: MatchedOrders, orders: MatchedOrders,
takerAddress: string, takerAddress: string,
tokenBalances: TokenBalances, tokenBalances: TokenBalances,
transferAmounts: MatchTransferAmounts, transferAmounts: MatchTransferAmounts,
): MatchResults { devUtils: DevUtilsContract,
): Promise<MatchResults> {
// prettier-ignore // prettier-ignore
const matchResults = { const matchResults = {
orders: { orders: {
@ -549,72 +540,80 @@ function simulateMatchOrders(
balances: _.cloneDeep(tokenBalances), balances: _.cloneDeep(tokenBalances),
}; };
// Right maker asset -> left maker // Right maker asset -> left maker
transferAsset( await transferAssetAsync(
orders.rightOrder.makerAddress, orders.rightOrder.makerAddress,
orders.leftOrder.makerAddress, orders.leftOrder.makerAddress,
transferAmounts.rightMakerAssetBoughtByLeftMakerAmount, transferAmounts.rightMakerAssetBoughtByLeftMakerAmount,
orders.rightOrder.makerAssetData, orders.rightOrder.makerAssetData,
matchResults, matchResults,
devUtils,
); );
if (orders.leftOrder.makerAddress !== orders.leftOrder.feeRecipientAddress) { if (orders.leftOrder.makerAddress !== orders.leftOrder.feeRecipientAddress) {
// Left maker fees // Left maker fees
transferAsset( await transferAssetAsync(
orders.leftOrder.makerAddress, orders.leftOrder.makerAddress,
orders.leftOrder.feeRecipientAddress, orders.leftOrder.feeRecipientAddress,
transferAmounts.leftMakerFeeAssetPaidByLeftMakerAmount, transferAmounts.leftMakerFeeAssetPaidByLeftMakerAmount,
orders.leftOrder.makerFeeAssetData, orders.leftOrder.makerFeeAssetData,
matchResults, matchResults,
devUtils,
); );
} }
// Left maker asset -> right maker // Left maker asset -> right maker
transferAsset( await transferAssetAsync(
orders.leftOrder.makerAddress, orders.leftOrder.makerAddress,
orders.rightOrder.makerAddress, orders.rightOrder.makerAddress,
transferAmounts.leftMakerAssetBoughtByRightMakerAmount, transferAmounts.leftMakerAssetBoughtByRightMakerAmount,
orders.leftOrder.makerAssetData, orders.leftOrder.makerAssetData,
matchResults, matchResults,
devUtils,
); );
if (orders.rightOrder.makerAddress !== orders.rightOrder.feeRecipientAddress) { if (orders.rightOrder.makerAddress !== orders.rightOrder.feeRecipientAddress) {
// Right maker fees // Right maker fees
transferAsset( await transferAssetAsync(
orders.rightOrder.makerAddress, orders.rightOrder.makerAddress,
orders.rightOrder.feeRecipientAddress, orders.rightOrder.feeRecipientAddress,
transferAmounts.rightMakerFeeAssetPaidByRightMakerAmount, transferAmounts.rightMakerFeeAssetPaidByRightMakerAmount,
orders.rightOrder.makerFeeAssetData, orders.rightOrder.makerFeeAssetData,
matchResults, matchResults,
devUtils,
); );
} }
// Left taker profit // Left taker profit
transferAsset( await transferAssetAsync(
orders.leftOrder.makerAddress, orders.leftOrder.makerAddress,
takerAddress, takerAddress,
transferAmounts.leftMakerAssetReceivedByTakerAmount, transferAmounts.leftMakerAssetReceivedByTakerAmount,
orders.leftOrder.makerAssetData, orders.leftOrder.makerAssetData,
matchResults, matchResults,
devUtils,
); );
// Right taker profit // Right taker profit
transferAsset( await transferAssetAsync(
orders.rightOrder.makerAddress, orders.rightOrder.makerAddress,
takerAddress, takerAddress,
transferAmounts.rightMakerAssetReceivedByTakerAmount, transferAmounts.rightMakerAssetReceivedByTakerAmount,
orders.rightOrder.makerAssetData, orders.rightOrder.makerAssetData,
matchResults, matchResults,
devUtils,
); );
// Left taker fees // Left taker fees
transferAsset( await transferAssetAsync(
takerAddress, takerAddress,
orders.leftOrder.feeRecipientAddress, orders.leftOrder.feeRecipientAddress,
transferAmounts.leftTakerFeeAssetPaidByTakerAmount, transferAmounts.leftTakerFeeAssetPaidByTakerAmount,
orders.leftOrder.takerFeeAssetData, orders.leftOrder.takerFeeAssetData,
matchResults, matchResults,
devUtils,
); );
// Right taker fees // Right taker fees
transferAsset( await transferAssetAsync(
takerAddress, takerAddress,
orders.rightOrder.feeRecipientAddress, orders.rightOrder.feeRecipientAddress,
transferAmounts.rightTakerFeeAssetPaidByTakerAmount, transferAmounts.rightTakerFeeAssetPaidByTakerAmount,
orders.rightOrder.takerFeeAssetData, orders.rightOrder.takerFeeAssetData,
matchResults, matchResults,
devUtils,
); );
return matchResults; return matchResults;
@ -624,18 +623,19 @@ function simulateMatchOrders(
* Simulates a transfer of assets from `fromAddress` to `toAddress` * Simulates a transfer of assets from `fromAddress` to `toAddress`
* by updating `matchResults`. * by updating `matchResults`.
*/ */
function transferAsset( async function transferAssetAsync(
fromAddress: string, fromAddress: string,
toAddress: string, toAddress: string,
amount: BigNumber, amount: BigNumber,
assetData: string, assetData: string,
matchResults: MatchResults, matchResults: MatchResults,
): void { devUtils: DevUtilsContract,
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData); ): Promise<void> {
const assetProxyId = await devUtils.decodeAssetProxyId.callAsync(assetData);
switch (assetProxyId) { switch (assetProxyId) {
case AssetProxyId.ERC20: { case AssetProxyId.ERC20: {
const erc20AssetData = assetDataUtils.decodeERC20AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const assetAddress = erc20AssetData.tokenAddress; const [proxyId, assetAddress] = await devUtils.decodeERC20AssetData.callAsync(assetData); // tslint:disable-line-no-unused-variable
const fromBalances = matchResults.balances.erc20[fromAddress]; const fromBalances = matchResults.balances.erc20[fromAddress];
const toBalances = matchResults.balances.erc20[toAddress]; const toBalances = matchResults.balances.erc20[toAddress];
fromBalances[assetAddress] = fromBalances[assetAddress].minus(amount); fromBalances[assetAddress] = fromBalances[assetAddress].minus(amount);
@ -643,9 +643,8 @@ function transferAsset(
break; break;
} }
case AssetProxyId.ERC721: { case AssetProxyId.ERC721: {
const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const assetAddress = erc721AssetData.tokenAddress; const [proxyId, assetAddress, tokenId] = await devUtils.decodeERC721AssetData.callAsync(assetData); // tslint:disable-line-no-unused-variable
const tokenId = erc721AssetData.tokenId;
const fromTokens = matchResults.balances.erc721[fromAddress][assetAddress]; const fromTokens = matchResults.balances.erc721[fromAddress][assetAddress];
const toTokens = matchResults.balances.erc721[toAddress][assetAddress]; const toTokens = matchResults.balances.erc721[toAddress][assetAddress];
if (amount.gte(1)) { if (amount.gte(1)) {
@ -658,13 +657,15 @@ function transferAsset(
break; break;
} }
case AssetProxyId.ERC1155: { case AssetProxyId.ERC1155: {
const erc1155AssetData = assetDataUtils.decodeERC1155AssetData(assetData); // tslint:disable-next-line:no-unused-variable
const assetAddress = erc1155AssetData.tokenAddress; const [proxyId, assetAddress, tokenIds, tokenValues] = await devUtils.decodeERC1155AssetData.callAsync(
assetData,
);
const fromBalances = matchResults.balances.erc1155[fromAddress][assetAddress]; const fromBalances = matchResults.balances.erc1155[fromAddress][assetAddress];
const toBalances = matchResults.balances.erc1155[toAddress][assetAddress]; const toBalances = matchResults.balances.erc1155[toAddress][assetAddress];
for (const i of _.times(erc1155AssetData.tokenIds.length)) { for (const i of _.times(tokenIds.length)) {
const tokenId = erc1155AssetData.tokenIds[i]; const tokenId = tokenIds[i];
const tokenValue = erc1155AssetData.tokenValues[i]; const tokenValue = tokenValues[i];
const tokenAmount = amount.times(tokenValue); const tokenAmount = amount.times(tokenValue);
if (tokenAmount.gt(0)) { if (tokenAmount.gt(0)) {
const tokenIndex = _.findIndex(fromBalances.nonFungible, t => t.eq(tokenId)); const tokenIndex = _.findIndex(fromBalances.nonFungible, t => t.eq(tokenId));
@ -683,11 +684,19 @@ function transferAsset(
break; break;
} }
case AssetProxyId.MultiAsset: { case AssetProxyId.MultiAsset: {
const multiAssetData = assetDataUtils.decodeMultiAssetData(assetData); // tslint:disable-next-line:no-unused-variable
for (const i of _.times(multiAssetData.amounts.length)) { const [proxyId, amounts, nestedAssetData] = await devUtils.decodeMultiAssetData.callAsync(assetData); // tslint:disable-line-no-unused-variable
const nestedAmount = amount.times(multiAssetData.amounts[i]); for (const i of _.times(amounts.length)) {
const nestedAssetData = multiAssetData.nestedAssetData[i]; const nestedAmount = amount.times(amounts[i]);
transferAsset(fromAddress, toAddress, nestedAmount, nestedAssetData, matchResults); const _nestedAssetData = nestedAssetData[i];
await transferAssetAsync(
fromAddress,
toAddress,
nestedAmount,
_nestedAssetData,
matchResults,
devUtils,
);
} }
break; break;
} }

View File

@ -1,5 +1,6 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, ERC1155HoldingsByOwner, ERC721TokenIdsByOwner } from '@0x/contracts-test-utils'; import { constants, ERC1155HoldingsByOwner, ERC721TokenIdsByOwner } from '@0x/contracts-test-utils';
import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils'; import { generatePseudoRandomSalt } from '@0x/order-utils';
import { Order } from '@0x/types'; import { Order } from '@0x/types';
import { BigNumber, errorUtils } from '@0x/utils'; import { BigNumber, errorUtils } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -32,40 +33,22 @@ const ONE_NFT_UNIT = new BigNumber(1);
const ZERO_UNITS = new BigNumber(0); const ZERO_UNITS = new BigNumber(0);
export class OrderFactoryFromScenario { export class OrderFactoryFromScenario {
private readonly _userAddresses: string[];
private readonly _erc20EighteenDecimalTokenAddresses: string[];
private readonly _erc20FiveDecimalTokenAddresses: string[];
private readonly _erc20ZeroDecimalTokenAddresses: string[];
private readonly _erc721TokenAddress: string;
private readonly _erc1155TokenAddress: string;
private readonly _erc721Balances: ERC721TokenIdsByOwner;
private readonly _erc1155Holdings: ERC1155HoldingsByOwner;
private readonly _exchangeAddress: string;
private readonly _chainId: number;
constructor( constructor(
userAddresses: string[], private readonly _devUtils: DevUtilsContract,
erc20EighteenDecimalTokenAddresses: string[], private readonly _userAddresses: string[],
erc20FiveDecimalTokenAddresses: string[], private readonly _erc20EighteenDecimalTokenAddresses: string[],
erc20ZeroDecimalTokenAddresses: string[], private readonly _erc20FiveDecimalTokenAddresses: string[],
erc721TokenAddress: string, private readonly _erc20ZeroDecimalTokenAddresses: string[],
erc1155TokenAddress: string, private readonly _erc721TokenAddress: string,
erc721Balances: ERC721TokenIdsByOwner, private readonly _erc1155TokenAddress: string,
erc1155Holdings: ERC1155HoldingsByOwner, private readonly _erc721Balances: ERC721TokenIdsByOwner,
exchangeAddress: string, private readonly _erc1155Holdings: ERC1155HoldingsByOwner,
chainId: number, private readonly _exchangeAddress: string,
private readonly _chainId: number,
) { ) {
this._userAddresses = userAddresses; return;
this._erc20EighteenDecimalTokenAddresses = erc20EighteenDecimalTokenAddresses;
this._erc20FiveDecimalTokenAddresses = erc20FiveDecimalTokenAddresses;
this._erc20ZeroDecimalTokenAddresses = erc20ZeroDecimalTokenAddresses;
this._erc721TokenAddress = erc721TokenAddress;
this._erc1155TokenAddress = erc1155TokenAddress;
this._erc721Balances = erc721Balances;
this._erc1155Holdings = erc1155Holdings;
this._exchangeAddress = exchangeAddress;
this._chainId = chainId;
} }
public generateOrder(orderScenario: OrderScenario): Order { public async generateOrderAsync(orderScenario: OrderScenario): Promise<Order> {
const makerAddress = this._userAddresses[1]; const makerAddress = this._userAddresses[1];
let takerAddress = this._userAddresses[2]; let takerAddress = this._userAddresses[2];
const erc721MakerAssetIds = this._erc721Balances[makerAddress][this._erc721TokenAddress]; const erc721MakerAssetIds = this._erc721Balances[makerAddress][this._erc721TokenAddress];
@ -113,19 +96,28 @@ export class OrderFactoryFromScenario {
switch (orderScenario.makerAssetDataScenario) { switch (orderScenario.makerAssetDataScenario) {
case AssetDataScenario.ERC20EighteenDecimals: case AssetDataScenario.ERC20EighteenDecimals:
makerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[0]); makerAssetData = await this._devUtils.encodeERC20AssetData.callAsync(
this._erc20EighteenDecimalTokenAddresses[0],
);
break; break;
case AssetDataScenario.ERC20FiveDecimals: case AssetDataScenario.ERC20FiveDecimals:
makerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[0]); makerAssetData = await this._devUtils.encodeERC20AssetData.callAsync(
this._erc20FiveDecimalTokenAddresses[0],
);
break; break;
case AssetDataScenario.ERC721: case AssetDataScenario.ERC721:
makerAssetData = assetDataUtils.encodeERC721AssetData(this._erc721TokenAddress, erc721MakerAssetIds[0]); makerAssetData = await this._devUtils.encodeERC721AssetData.callAsync(
this._erc721TokenAddress,
erc721MakerAssetIds[0],
);
break; break;
case AssetDataScenario.ERC20ZeroDecimals: case AssetDataScenario.ERC20ZeroDecimals:
makerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[0]); makerAssetData = await this._devUtils.encodeERC20AssetData.callAsync(
this._erc20ZeroDecimalTokenAddresses[0],
);
break; break;
case AssetDataScenario.ERC1155Fungible: case AssetDataScenario.ERC1155Fungible:
makerAssetData = assetDataUtils.encodeERC1155AssetData( makerAssetData = await this._devUtils.encodeERC1155AssetData.callAsync(
this._erc1155TokenAddress, this._erc1155TokenAddress,
[erc1155FungibleMakerTokenIds[0]], [erc1155FungibleMakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS], [ONE_UNITS_ZERO_DECIMALS],
@ -133,7 +125,7 @@ export class OrderFactoryFromScenario {
); );
break; break;
case AssetDataScenario.ERC1155NonFungible: case AssetDataScenario.ERC1155NonFungible:
makerAssetData = assetDataUtils.encodeERC1155AssetData( makerAssetData = await this._devUtils.encodeERC1155AssetData.callAsync(
this._erc1155TokenAddress, this._erc1155TokenAddress,
[erc1155NonFungibleMakerTokenIds[0]], [erc1155NonFungibleMakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS], [ONE_UNITS_ZERO_DECIMALS],
@ -141,11 +133,13 @@ export class OrderFactoryFromScenario {
); );
break; break;
case AssetDataScenario.MultiAssetERC20: case AssetDataScenario.MultiAssetERC20:
makerAssetData = assetDataUtils.encodeMultiAssetData( makerAssetData = await this._devUtils.encodeMultiAssetData.callAsync(
[ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS], [ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS],
[ [
assetDataUtils.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[0]), await this._devUtils.encodeERC20AssetData.callAsync(
assetDataUtils.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[0]), this._erc20EighteenDecimalTokenAddresses[0],
),
await this._devUtils.encodeERC20AssetData.callAsync(this._erc20FiveDecimalTokenAddresses[0]),
], ],
); );
break; break;
@ -155,19 +149,28 @@ export class OrderFactoryFromScenario {
switch (orderScenario.takerAssetDataScenario) { switch (orderScenario.takerAssetDataScenario) {
case AssetDataScenario.ERC20EighteenDecimals: case AssetDataScenario.ERC20EighteenDecimals:
takerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[1]); takerAssetData = await this._devUtils.encodeERC20AssetData.callAsync(
this._erc20EighteenDecimalTokenAddresses[1],
);
break; break;
case AssetDataScenario.ERC20FiveDecimals: case AssetDataScenario.ERC20FiveDecimals:
takerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[1]); takerAssetData = await this._devUtils.encodeERC20AssetData.callAsync(
this._erc20FiveDecimalTokenAddresses[1],
);
break; break;
case AssetDataScenario.ERC721: case AssetDataScenario.ERC721:
takerAssetData = assetDataUtils.encodeERC721AssetData(this._erc721TokenAddress, erc721TakerAssetIds[0]); takerAssetData = await this._devUtils.encodeERC721AssetData.callAsync(
this._erc721TokenAddress,
erc721TakerAssetIds[0],
);
break; break;
case AssetDataScenario.ERC20ZeroDecimals: case AssetDataScenario.ERC20ZeroDecimals:
takerAssetData = assetDataUtils.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[1]); takerAssetData = await this._devUtils.encodeERC20AssetData.callAsync(
this._erc20ZeroDecimalTokenAddresses[1],
);
break; break;
case AssetDataScenario.ERC1155Fungible: case AssetDataScenario.ERC1155Fungible:
takerAssetData = assetDataUtils.encodeERC1155AssetData( takerAssetData = await this._devUtils.encodeERC1155AssetData.callAsync(
this._erc1155TokenAddress, this._erc1155TokenAddress,
[erc1155FungibleTakerTokenIds[1]], [erc1155FungibleTakerTokenIds[1]],
[ONE_UNITS_ZERO_DECIMALS], [ONE_UNITS_ZERO_DECIMALS],
@ -175,7 +178,7 @@ export class OrderFactoryFromScenario {
); );
break; break;
case AssetDataScenario.ERC1155NonFungible: case AssetDataScenario.ERC1155NonFungible:
takerAssetData = assetDataUtils.encodeERC1155AssetData( takerAssetData = await this._devUtils.encodeERC1155AssetData.callAsync(
this._erc1155TokenAddress, this._erc1155TokenAddress,
[erc1155NonFungibleTakerTokenIds[0]], [erc1155NonFungibleTakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS], [ONE_UNITS_ZERO_DECIMALS],
@ -183,11 +186,13 @@ export class OrderFactoryFromScenario {
); );
break; break;
case AssetDataScenario.MultiAssetERC20: case AssetDataScenario.MultiAssetERC20:
takerAssetData = assetDataUtils.encodeMultiAssetData( takerAssetData = await this._devUtils.encodeMultiAssetData.callAsync(
[ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS], [ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS],
[ [
assetDataUtils.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[1]), await this._devUtils.encodeERC20AssetData.callAsync(
assetDataUtils.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[1]), this._erc20EighteenDecimalTokenAddresses[1],
),
await this._devUtils.encodeERC20AssetData.callAsync(this._erc20FiveDecimalTokenAddresses[1]),
], ],
); );
break; break;
@ -303,7 +308,7 @@ export class OrderFactoryFromScenario {
throw errorUtils.spawnSwitchErr('OrderAssetAmountScenario', orderScenario.takerAssetAmountScenario); throw errorUtils.spawnSwitchErr('OrderAssetAmountScenario', orderScenario.takerAssetAmountScenario);
} }
const feeFromScenario = ( const feeFromScenario = async (
feeAmountScenario: OrderAssetAmountScenario, feeAmountScenario: OrderAssetAmountScenario,
feeAssetDataScenario: FeeAssetDataScenario, feeAssetDataScenario: FeeAssetDataScenario,
erc20EighteenDecimalTokenAddress: string, erc20EighteenDecimalTokenAddress: string,
@ -312,7 +317,7 @@ export class OrderFactoryFromScenario {
erc721AssetId: BigNumber, erc721AssetId: BigNumber,
erc1155FungibleTokenId: BigNumber, erc1155FungibleTokenId: BigNumber,
erc1155NonFungibleAssetId: BigNumber, erc1155NonFungibleAssetId: BigNumber,
): [BigNumber, string] => { ): Promise<[BigNumber, string]> => {
const feeAmount = getFeeAmountFromScenario(orderScenario, feeAssetDataScenario, feeAmountScenario); const feeAmount = getFeeAmountFromScenario(orderScenario, feeAssetDataScenario, feeAmountScenario);
switch (feeAssetDataScenario) { switch (feeAssetDataScenario) {
case FeeAssetDataScenario.MakerToken: case FeeAssetDataScenario.MakerToken:
@ -320,17 +325,29 @@ export class OrderFactoryFromScenario {
case FeeAssetDataScenario.TakerToken: case FeeAssetDataScenario.TakerToken:
return [feeAmount, takerAssetData]; return [feeAmount, takerAssetData];
case FeeAssetDataScenario.ERC20EighteenDecimals: case FeeAssetDataScenario.ERC20EighteenDecimals:
return [feeAmount, assetDataUtils.encodeERC20AssetData(erc20EighteenDecimalTokenAddress)]; return [
feeAmount,
await this._devUtils.encodeERC20AssetData.callAsync(erc20EighteenDecimalTokenAddress),
];
case FeeAssetDataScenario.ERC20FiveDecimals: case FeeAssetDataScenario.ERC20FiveDecimals:
return [feeAmount, assetDataUtils.encodeERC20AssetData(erc20FiveDecimalTokenAddress)]; return [
feeAmount,
await this._devUtils.encodeERC20AssetData.callAsync(erc20FiveDecimalTokenAddress),
];
case FeeAssetDataScenario.ERC20ZeroDecimals: case FeeAssetDataScenario.ERC20ZeroDecimals:
return [feeAmount, assetDataUtils.encodeERC20AssetData(erc20ZeroDecimalTokenAddress)]; return [
feeAmount,
await this._devUtils.encodeERC20AssetData.callAsync(erc20ZeroDecimalTokenAddress),
];
case FeeAssetDataScenario.ERC721: case FeeAssetDataScenario.ERC721:
return [feeAmount, assetDataUtils.encodeERC721AssetData(this._erc721TokenAddress, erc721AssetId)]; return [
feeAmount,
await this._devUtils.encodeERC721AssetData.callAsync(this._erc721TokenAddress, erc721AssetId),
];
case FeeAssetDataScenario.ERC1155Fungible: case FeeAssetDataScenario.ERC1155Fungible:
return [ return [
feeAmount, feeAmount,
assetDataUtils.encodeERC1155AssetData( await this._devUtils.encodeERC1155AssetData.callAsync(
this._erc1155TokenAddress, this._erc1155TokenAddress,
[erc1155FungibleTokenId], [erc1155FungibleTokenId],
[ONE_UNITS_ZERO_DECIMALS], [ONE_UNITS_ZERO_DECIMALS],
@ -340,7 +357,7 @@ export class OrderFactoryFromScenario {
case FeeAssetDataScenario.ERC1155NonFungible: case FeeAssetDataScenario.ERC1155NonFungible:
return [ return [
feeAmount, feeAmount,
assetDataUtils.encodeERC1155AssetData( await this._devUtils.encodeERC1155AssetData.callAsync(
this._erc1155TokenAddress, this._erc1155TokenAddress,
[erc1155NonFungibleAssetId], [erc1155NonFungibleAssetId],
[ONE_UNITS_ZERO_DECIMALS], [ONE_UNITS_ZERO_DECIMALS],
@ -350,11 +367,11 @@ export class OrderFactoryFromScenario {
case FeeAssetDataScenario.MultiAssetERC20: case FeeAssetDataScenario.MultiAssetERC20:
return [ return [
feeAmount, feeAmount,
assetDataUtils.encodeMultiAssetData( await this._devUtils.encodeMultiAssetData.callAsync(
[POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS, POINT_ZERO_FIVE_UNITS_FIVE_DECIMALS], [POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS, POINT_ZERO_FIVE_UNITS_FIVE_DECIMALS],
[ [
assetDataUtils.encodeERC20AssetData(erc20EighteenDecimalTokenAddress), await this._devUtils.encodeERC20AssetData.callAsync(erc20EighteenDecimalTokenAddress),
assetDataUtils.encodeERC20AssetData(erc20FiveDecimalTokenAddress), await this._devUtils.encodeERC20AssetData.callAsync(erc20FiveDecimalTokenAddress),
], ],
), ),
]; ];
@ -363,7 +380,7 @@ export class OrderFactoryFromScenario {
} }
}; };
[makerFee, makerFeeAssetData] = feeFromScenario( [makerFee, makerFeeAssetData] = await feeFromScenario(
orderScenario.makerFeeScenario, orderScenario.makerFeeScenario,
orderScenario.makerFeeAssetDataScenario, orderScenario.makerFeeAssetDataScenario,
this._erc20EighteenDecimalTokenAddresses[2], this._erc20EighteenDecimalTokenAddresses[2],
@ -373,7 +390,7 @@ export class OrderFactoryFromScenario {
erc1155FungibleMakerTokenIds[2], erc1155FungibleMakerTokenIds[2],
erc1155NonFungibleMakerTokenIds[1], erc1155NonFungibleMakerTokenIds[1],
); );
[takerFee, takerFeeAssetData] = feeFromScenario( [takerFee, takerFeeAssetData] = await feeFromScenario(
orderScenario.takerFeeScenario, orderScenario.takerFeeScenario,
orderScenario.takerFeeAssetDataScenario, orderScenario.takerFeeAssetDataScenario,
this._erc20EighteenDecimalTokenAddresses[3], this._erc20EighteenDecimalTokenAddresses[3],

View File

@ -73,6 +73,7 @@
"dependencies": { "dependencies": {
"@0x/base-contract": "^5.5.0-beta.0", "@0x/base-contract": "^5.5.0-beta.0",
"@0x/contracts-asset-proxy": "^2.3.0-beta.0", "@0x/contracts-asset-proxy": "^2.3.0-beta.0",
"@0x/contracts-dev-utils": "^0.1.0-beta.0",
"@0x/contracts-erc20": "^2.3.0-beta.0", "@0x/contracts-erc20": "^2.3.0-beta.0",
"@0x/contracts-erc721": "^2.2.0-beta.0", "@0x/contracts-erc721": "^2.2.0-beta.0",
"@0x/contracts-exchange": "^2.2.0-beta.0", "@0x/contracts-exchange": "^2.2.0-beta.0",

View File

@ -1,6 +1,7 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange'; import { ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, ExchangeRevertErrors } from '@0x/order-utils'; import { ExchangeRevertErrors } from '@0x/order-utils';
import { Order, RevertReason, SignedOrder } from '@0x/types'; import { Order, RevertReason, SignedOrder } from '@0x/types';
import { BigNumber, providerUtils } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
@ -52,6 +53,7 @@ describe(ContractName.BalanceThresholdFilter, () => {
let zrxToken: DummyERC20TokenContract; let zrxToken: DummyERC20TokenContract;
let exchangeInstance: ExchangeContract; let exchangeInstance: ExchangeContract;
let exchangeWrapper: ExchangeWrapper; let exchangeWrapper: ExchangeWrapper;
let devUtils: DevUtilsContract;
let orderFactory: OrderFactory; let orderFactory: OrderFactory;
let orderFactory2: OrderFactory; let orderFactory2: OrderFactory;
@ -105,6 +107,7 @@ describe(ContractName.BalanceThresholdFilter, () => {
const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validMakerAddress)]; const makerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validMakerAddress)];
const secondMakerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validMakerAddress2)]; const secondMakerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(validMakerAddress2)];
const invalidAddressPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(invalidAddress)]; const invalidAddressPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(invalidAddress)];
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
// Create wrappers // Create wrappers
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
const validAddresses = _.cloneDeepWith(usedAddresses); const validAddresses = _.cloneDeepWith(usedAddresses);
@ -123,7 +126,7 @@ describe(ContractName.BalanceThresholdFilter, () => {
); );
defaultMakerAssetAddress = erc20TokenA.address; defaultMakerAssetAddress = erc20TokenA.address;
defaultTakerAssetAddress = erc20TokenB.address; defaultTakerAssetAddress = erc20TokenB.address;
zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); zrxAssetData = await devUtils.encodeERC20AssetData.callAsync(zrxToken.address);
// Create proxies // Create proxies
const erc20Proxy = await erc20Wrapper.deployProxyAsync(); const erc20Proxy = await erc20Wrapper.deployProxyAsync();
await erc20Wrapper.setBalancesAndAllowancesAsync(); await erc20Wrapper.setBalancesAndAllowancesAsync();
@ -170,8 +173,8 @@ describe(ContractName.BalanceThresholdFilter, () => {
// Default order parameters // Default order parameters
defaultOrderParams = { defaultOrderParams = {
feeRecipientAddress, feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultMakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerAssetAddress),
makerAssetAmount, makerAssetAmount,
takerAssetAmount, takerAssetAmount,
makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS_DEFAULT), makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), DECIMALS_DEFAULT),
@ -1236,8 +1239,8 @@ describe(ContractName.BalanceThresholdFilter, () => {
feeRecipientAddress, feeRecipientAddress,
}); });
const signedOrderRight = await orderFactory2.newSignedOrderAsync({ const signedOrderRight = await orderFactory2.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerAssetAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultMakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(75), 0),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(13), 0),
makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18), makerFee: Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18),

View File

@ -1,4 +1,5 @@
import { ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { DummyERC721TokenContract } from '@0x/contracts-erc721'; import { DummyERC721TokenContract } from '@0x/contracts-erc721';
import { ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange'; import { ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange';
@ -59,6 +60,8 @@ describe(ContractName.DutchAuction, () => {
let dutchAuctionTestWrapper: DutchAuctionTestWrapper; let dutchAuctionTestWrapper: DutchAuctionTestWrapper;
let defaultERC20MakerAssetData: string; let defaultERC20MakerAssetData: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
before(async () => { before(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
@ -86,7 +89,7 @@ describe(ContractName.DutchAuction, () => {
wethContract = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.WETH9, provider, txDefaults, artifacts); wethContract = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.WETH9, provider, txDefaults, artifacts);
erc20Wrapper.addDummyTokenContract(wethContract as any); erc20Wrapper.addDummyTokenContract(wethContract as any);
const zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address); const zrxAssetData = await devUtils.encodeERC20AssetData.callAsync(zrxToken.address);
const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync( const exchangeInstance = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange, artifacts.Exchange,
provider, provider,
@ -153,11 +156,11 @@ describe(ContractName.DutchAuction, () => {
// taker address or sender address should be set to the ducth auction contract // taker address or sender address should be set to the ducth auction contract
takerAddress: dutchAuctionContract.address, takerAddress: dutchAuctionContract.address,
makerAssetData: assetDataUtils.encodeDutchAuctionAssetData( makerAssetData: assetDataUtils.encodeDutchAuctionAssetData(
assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), await devUtils.encodeERC20AssetData.callAsync(defaultMakerAssetAddress),
auctionBeginTimeSeconds, auctionBeginTimeSeconds,
auctionBeginAmount, auctionBeginAmount,
), ),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerAssetAddress), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerAssetAddress),
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), DECIMALS_DEFAULT),
takerAssetAmount: auctionEndAmount, takerAssetAmount: auctionEndAmount,
expirationTimeSeconds: auctionEndTimeSeconds, expirationTimeSeconds: auctionEndTimeSeconds,
@ -179,7 +182,7 @@ describe(ContractName.DutchAuction, () => {
const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)]; const takerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(takerAddress)];
sellerOrderFactory = new OrderFactory(makerPrivateKey, sellerDefaultOrderParams); sellerOrderFactory = new OrderFactory(makerPrivateKey, sellerDefaultOrderParams);
buyerOrderFactory = new OrderFactory(takerPrivateKey, buyerDefaultOrderParams); buyerOrderFactory = new OrderFactory(takerPrivateKey, buyerDefaultOrderParams);
defaultERC20MakerAssetData = assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress); defaultERC20MakerAssetData = await devUtils.encodeERC20AssetData.callAsync(defaultMakerAssetAddress);
}); });
after(async () => { after(async () => {
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
@ -318,7 +321,7 @@ describe(ContractName.DutchAuction, () => {
}); });
it('asset data contains auction parameters', async () => { it('asset data contains auction parameters', async () => {
sellOrder = await sellerOrderFactory.newSignedOrderAsync({ sellOrder = await sellerOrderFactory.newSignedOrderAsync({
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerAssetAddress), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultMakerAssetAddress),
}); });
const tx = dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress); const tx = dutchAuctionTestWrapper.matchOrdersAsync(buyOrder, sellOrder, takerAddress);
return expect(tx).to.revertWith(RevertReason.InvalidAssetData); return expect(tx).to.revertWith(RevertReason.InvalidAssetData);
@ -327,7 +330,10 @@ describe(ContractName.DutchAuction, () => {
describe('ERC721', () => { describe('ERC721', () => {
it('should match orders when ERC721', async () => { it('should match orders when ERC721', async () => {
const makerAssetId = erc721MakerAssetIds[0]; const makerAssetId = erc721MakerAssetIds[0];
const erc721MakerAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, makerAssetId); const erc721MakerAssetData = await devUtils.encodeERC721AssetData.callAsync(
erc721Token.address,
makerAssetId,
);
const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData( const makerAssetData = assetDataUtils.encodeDutchAuctionAssetData(
erc721MakerAssetData, erc721MakerAssetData,
auctionBeginTimeSeconds, auctionBeginTimeSeconds,

View File

@ -4,6 +4,7 @@ import {
ERC20Wrapper, ERC20Wrapper,
ERC721ProxyContract, ERC721ProxyContract,
} from '@0x/contracts-asset-proxy'; } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721'; import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
import { ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange'; import { ExchangeContract, ExchangeWrapper } from '@0x/contracts-exchange';
@ -20,7 +21,7 @@ import {
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, ExchangeRevertErrors } from '@0x/order-utils'; import { ExchangeRevertErrors } from '@0x/order-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { BigNumber, providerUtils } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
@ -62,6 +63,7 @@ describe('OrderMatcher', () => {
let defaultERC20MakerAssetAddress: string; let defaultERC20MakerAssetAddress: string;
let defaultERC20TakerAssetAddress: string; let defaultERC20TakerAssetAddress: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider, txDefaults);
before(async () => { before(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
}); });
@ -112,7 +114,7 @@ describe('OrderMatcher', () => {
provider, provider,
txDefaults, txDefaults,
artifacts, artifacts,
assetDataUtils.encodeERC20AssetData(zrxToken.address), await devUtils.encodeERC20AssetData.callAsync(zrxToken.address),
new BigNumber(chainId), new BigNumber(chainId),
); );
exchangeWrapper = new ExchangeWrapper(exchange); exchangeWrapper = new ExchangeWrapper(exchange);
@ -136,8 +138,8 @@ describe('OrderMatcher', () => {
// Set default addresses // Set default addresses
defaultERC20MakerAssetAddress = erc20TokenA.address; defaultERC20MakerAssetAddress = erc20TokenA.address;
defaultERC20TakerAssetAddress = erc20TokenB.address; defaultERC20TakerAssetAddress = erc20TokenB.address;
leftMakerAssetData = assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress); leftMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(defaultERC20MakerAssetAddress);
leftTakerAssetData = assetDataUtils.encodeERC20AssetData(defaultERC20TakerAssetAddress); leftTakerAssetData = await devUtils.encodeERC20AssetData.callAsync(defaultERC20TakerAssetAddress);
// Set OrderMatcher balances and allowances // Set OrderMatcher balances and allowances
await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.awaitTransactionSuccessAsync(
await erc20TokenA.setBalance.sendTransactionAsync(orderMatcher.address, constants.INITIAL_ERC20_BALANCE, { await erc20TokenA.setBalance.sendTransactionAsync(orderMatcher.address, constants.INITIAL_ERC20_BALANCE, {
@ -743,7 +745,7 @@ describe('OrderMatcher', () => {
await erc721Token.mint.sendTransactionAsync(orderMatcher.address, tokenId, { from: owner }), await erc721Token.mint.sendTransactionAsync(orderMatcher.address, tokenId, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS, constants.AWAIT_TRANSACTION_MINED_MS,
); );
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId); const assetData = await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, tokenId);
const withdrawAmount = new BigNumber(1); const withdrawAmount = new BigNumber(1);
await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.awaitTransactionSuccessAsync(
await orderMatcher.withdrawAsset.sendTransactionAsync(assetData, withdrawAmount, { from: owner }), await orderMatcher.withdrawAsset.sendTransactionAsync(assetData, withdrawAmount, { from: owner }),
@ -782,7 +784,10 @@ describe('OrderMatcher', () => {
constants.DUMMY_TOKEN_NAME, constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL, constants.DUMMY_TOKEN_SYMBOL,
); );
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, constants.ZERO_AMOUNT); const assetData = await devUtils.encodeERC721AssetData.callAsync(
erc721Token.address,
constants.ZERO_AMOUNT,
);
const allowance = new BigNumber(1); const allowance = new BigNumber(1);
await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.awaitTransactionSuccessAsync(
await orderMatcher.approveAssetProxy.sendTransactionAsync(assetData, allowance, { from: owner }), await orderMatcher.approveAssetProxy.sendTransactionAsync(assetData, allowance, { from: owner }),
@ -800,7 +805,10 @@ describe('OrderMatcher', () => {
constants.DUMMY_TOKEN_NAME, constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL, constants.DUMMY_TOKEN_SYMBOL,
); );
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, constants.ZERO_AMOUNT); const assetData = await devUtils.encodeERC721AssetData.callAsync(
erc721Token.address,
constants.ZERO_AMOUNT,
);
const allowance = new BigNumber(2); const allowance = new BigNumber(2);
await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.awaitTransactionSuccessAsync(
await orderMatcher.approveAssetProxy.sendTransactionAsync(assetData, allowance, { from: owner }), await orderMatcher.approveAssetProxy.sendTransactionAsync(assetData, allowance, { from: owner }),

View File

@ -1,4 +1,5 @@
import { CoordinatorContract, SignedCoordinatorApproval } from '@0x/contracts-coordinator'; import { CoordinatorContract, SignedCoordinatorApproval } from '@0x/contracts-coordinator';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { import {
BlockchainBalanceStore, BlockchainBalanceStore,
constants as exchangeConstants, constants as exchangeConstants,
@ -10,8 +11,16 @@ import {
ExchangeFunctionName, ExchangeFunctionName,
LocalBalanceStore, LocalBalanceStore,
} from '@0x/contracts-exchange'; } from '@0x/contracts-exchange';
import { blockchainTests, constants, expect, hexConcat, hexSlice, verifyEvents } from '@0x/contracts-test-utils'; import {
import { assetDataUtils, CoordinatorRevertErrors, orderHashUtils, transactionHashUtils } from '@0x/order-utils'; blockchainTests,
constants,
expect,
hexConcat,
hexSlice,
provider,
verifyEvents,
} from '@0x/contracts-test-utils';
import { CoordinatorRevertErrors, orderHashUtils, transactionHashUtils } from '@0x/order-utils';
import { SignedOrder, SignedZeroExTransaction } from '@0x/types'; import { SignedOrder, SignedZeroExTransaction } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -26,6 +35,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
let deployment: DeploymentManager; let deployment: DeploymentManager;
let coordinator: CoordinatorContract; let coordinator: CoordinatorContract;
let balanceStore: BlockchainBalanceStore; let balanceStore: BlockchainBalanceStore;
let devUtils: DevUtilsContract;
let maker: Maker; let maker: Maker;
let taker: Actor; let taker: Actor;
@ -38,6 +48,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
numErc1155TokensToDeploy: 0, numErc1155TokensToDeploy: 0,
}); });
coordinator = await deployCoordinatorAsync(deployment, env); coordinator = await deployCoordinatorAsync(deployment, env);
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
const [makerToken, takerToken, makerFeeToken, takerFeeToken] = deployment.tokens.erc20; const [makerToken, takerToken, makerFeeToken, takerFeeToken] = deployment.tokens.erc20;
@ -53,10 +64,10 @@ blockchainTests.resets('Coordinator integration tests', env => {
orderConfig: { orderConfig: {
senderAddress: coordinator.address, senderAddress: coordinator.address,
feeRecipientAddress: feeRecipient.address, feeRecipientAddress: feeRecipient.address,
makerAssetData: assetDataUtils.encodeERC20AssetData(makerToken.address), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(makerToken.address),
takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken.address), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(takerToken.address),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerFeeToken.address), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(makerFeeToken.address),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(takerFeeToken.address), takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(takerFeeToken.address),
}, },
}); });
@ -77,30 +88,40 @@ blockchainTests.resets('Coordinator integration tests', env => {
); );
}); });
function simulateFills( async function simulateFillsAsync(
orders: SignedOrder[], orders: SignedOrder[],
txReceipt: TransactionReceiptWithDecodedLogs, txReceipt: TransactionReceiptWithDecodedLogs,
msgValue?: BigNumber, msgValue?: BigNumber,
): LocalBalanceStore { ): Promise<LocalBalanceStore> {
let remainingValue = msgValue || constants.ZERO_AMOUNT; let remainingValue = msgValue || constants.ZERO_AMOUNT;
const localBalanceStore = LocalBalanceStore.create(balanceStore); const localBalanceStore = LocalBalanceStore.create(devUtils, balanceStore);
// Transaction gas cost // Transaction gas cost
localBalanceStore.burnGas(txReceipt.from, DeploymentManager.gasPrice.times(txReceipt.gasUsed)); localBalanceStore.burnGas(txReceipt.from, DeploymentManager.gasPrice.times(txReceipt.gasUsed));
for (const order of orders) { for (const order of orders) {
// Taker -> Maker // Taker -> Maker
localBalanceStore.transferAsset(taker.address, maker.address, order.takerAssetAmount, order.takerAssetData); await localBalanceStore.transferAssetAsync(
taker.address,
maker.address,
order.takerAssetAmount,
order.takerAssetData,
);
// Maker -> Taker // Maker -> Taker
localBalanceStore.transferAsset(maker.address, taker.address, order.makerAssetAmount, order.makerAssetData); await localBalanceStore.transferAssetAsync(
maker.address,
taker.address,
order.makerAssetAmount,
order.makerAssetData,
);
// Taker -> Fee Recipient // Taker -> Fee Recipient
localBalanceStore.transferAsset( await localBalanceStore.transferAssetAsync(
taker.address, taker.address,
feeRecipient.address, feeRecipient.address,
order.takerFee, order.takerFee,
order.takerFeeAssetData, order.takerFeeAssetData,
); );
// Maker -> Fee Recipient // Maker -> Fee Recipient
localBalanceStore.transferAsset( await localBalanceStore.transferAssetAsync(
maker.address, maker.address,
feeRecipient.address, feeRecipient.address,
order.makerFee, order.makerFee,
@ -116,11 +137,11 @@ blockchainTests.resets('Coordinator integration tests', env => {
); );
remainingValue = remainingValue.minus(DeploymentManager.protocolFee); remainingValue = remainingValue.minus(DeploymentManager.protocolFee);
} else { } else {
localBalanceStore.transferAsset( await localBalanceStore.transferAssetAsync(
taker.address, taker.address,
deployment.staking.stakingProxy.address, deployment.staking.stakingProxy.address,
DeploymentManager.protocolFee, DeploymentManager.protocolFee,
assetDataUtils.encodeERC20AssetData(deployment.tokens.weth.address), await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.weth.address),
); );
} }
} }
@ -174,7 +195,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: taker.address, value: DeploymentManager.protocolFee }, { from: taker.address, value: DeploymentManager.protocolFee },
); );
const expectedBalances = simulateFills([order], txReceipt, DeploymentManager.protocolFee); const expectedBalances = await simulateFillsAsync([order], txReceipt, DeploymentManager.protocolFee);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill); verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -189,7 +210,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address, value: DeploymentManager.protocolFee }, { from: feeRecipient.address, value: DeploymentManager.protocolFee },
); );
const expectedBalances = simulateFills([order], txReceipt, DeploymentManager.protocolFee); const expectedBalances = await simulateFillsAsync([order], txReceipt, DeploymentManager.protocolFee);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill); verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -204,7 +225,11 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address, value: DeploymentManager.protocolFee.plus(1) }, { from: feeRecipient.address, value: DeploymentManager.protocolFee.plus(1) },
); );
const expectedBalances = simulateFills([order], txReceipt, DeploymentManager.protocolFee.plus(1)); const expectedBalances = await simulateFillsAsync(
[order],
txReceipt,
DeploymentManager.protocolFee.plus(1),
);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill); verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -219,7 +244,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address }, { from: feeRecipient.address },
); );
const expectedBalances = simulateFills([order], txReceipt); const expectedBalances = await simulateFillsAsync([order], txReceipt);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill); verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -234,7 +259,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address, value: new BigNumber(1) }, { from: feeRecipient.address, value: new BigNumber(1) },
); );
const expectedBalances = simulateFills([order], txReceipt, new BigNumber(1)); const expectedBalances = await simulateFillsAsync([order], txReceipt, new BigNumber(1));
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill); verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -318,7 +343,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: taker.address, value }, { from: taker.address, value },
); );
const expectedBalances = simulateFills(orders, txReceipt, value); const expectedBalances = await simulateFillsAsync(orders, txReceipt, value);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill); verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill);
@ -334,7 +359,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address, value }, { from: feeRecipient.address, value },
); );
const expectedBalances = simulateFills(orders, txReceipt, value); const expectedBalances = await simulateFillsAsync(orders, txReceipt, value);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill); verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill);
@ -350,7 +375,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address, value }, { from: feeRecipient.address, value },
); );
const expectedBalances = simulateFills(orders, txReceipt, value); const expectedBalances = await simulateFillsAsync(orders, txReceipt, value);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill); verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill);

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { DummyERC721TokenContract } from '@0x/contracts-erc721'; import { DummyERC721TokenContract } from '@0x/contracts-erc721';
import { import {
@ -13,9 +14,10 @@ import {
expect, expect,
getLatestBlockTimestampAsync, getLatestBlockTimestampAsync,
getPercentageOfValue, getPercentageOfValue,
provider,
toBaseUnitAmount, toBaseUnitAmount,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { assetDataUtils, ForwarderRevertErrors } from '@0x/order-utils'; import { ForwarderRevertErrors } from '@0x/order-utils';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { Actor, actorAddressesByName, FeeRecipient, Maker } from '../actors'; import { Actor, actorAddressesByName, FeeRecipient, Maker } from '../actors';
@ -24,6 +26,8 @@ import { DeploymentManager } from '../utils/deployment_manager';
import { deployForwarderAsync } from './deploy_forwarder'; import { deployForwarderAsync } from './deploy_forwarder';
import { ForwarderTestFactory } from './forwarder_test_factory'; import { ForwarderTestFactory } from './forwarder_test_factory';
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
blockchainTests('Forwarder integration tests', env => { blockchainTests('Forwarder integration tests', env => {
let deployment: DeploymentManager; let deployment: DeploymentManager;
let forwarder: ForwarderContract; let forwarder: ForwarderContract;
@ -53,8 +57,8 @@ blockchainTests('Forwarder integration tests', env => {
[makerToken, makerFeeToken, anotherErc20Token] = deployment.tokens.erc20; [makerToken, makerFeeToken, anotherErc20Token] = deployment.tokens.erc20;
[erc721Token] = deployment.tokens.erc721; [erc721Token] = deployment.tokens.erc721;
wethAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.weth.address); wethAssetData = await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.weth.address);
makerAssetData = assetDataUtils.encodeERC20AssetData(makerToken.address); makerAssetData = await devUtils.encodeERC20AssetData.callAsync(makerToken.address);
taker = new Actor({ name: 'Taker', deployment }); taker = new Actor({ name: 'Taker', deployment });
orderFeeRecipient = new FeeRecipient({ orderFeeRecipient = new FeeRecipient({
@ -75,7 +79,7 @@ blockchainTests('Forwarder integration tests', env => {
makerAssetData, makerAssetData,
takerAssetData: wethAssetData, takerAssetData: wethAssetData,
takerFee: constants.ZERO_AMOUNT, takerFee: constants.ZERO_AMOUNT,
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerFeeToken.address), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(makerFeeToken.address),
takerFeeAssetData: wethAssetData, takerFeeAssetData: wethAssetData,
}, },
}); });
@ -106,6 +110,7 @@ blockchainTests('Forwarder integration tests', env => {
taker, taker,
orderFeeRecipient, orderFeeRecipient,
forwarderFeeRecipient, forwarderFeeRecipient,
devUtils,
); );
}); });
@ -166,7 +171,7 @@ blockchainTests('Forwarder integration tests', env => {
await testFactory.marketSellTestAsync(orders, 1.34); await testFactory.marketSellTestAsync(orders, 1.34);
}); });
it('should fail to fill an order with a percentage fee if the asset proxy is not yet approved', async () => { it('should fail to fill an order with a percentage fee if the asset proxy is not yet approved', async () => {
const unapprovedAsset = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address); const unapprovedAsset = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const order = await maker.signOrderAsync({ const order = await maker.signOrderAsync({
makerAssetData: unapprovedAsset, makerAssetData: unapprovedAsset,
takerFee: toBaseUnitAmount(2), takerFee: toBaseUnitAmount(2),
@ -186,7 +191,7 @@ blockchainTests('Forwarder integration tests', env => {
}, },
); );
const expectedBalances = LocalBalanceStore.create(balanceStore); const expectedBalances = LocalBalanceStore.create(devUtils, balanceStore);
expectedBalances.burnGas(tx.from, DeploymentManager.gasPrice.times(tx.gasUsed)); expectedBalances.burnGas(tx.from, DeploymentManager.gasPrice.times(tx.gasUsed));
// Verify balances // Verify balances
@ -236,7 +241,7 @@ blockchainTests('Forwarder integration tests', env => {
}); });
it('should fill orders with different makerAssetData', async () => { it('should fill orders with different makerAssetData', async () => {
const firstOrder = await maker.signOrderAsync(); const firstOrder = await maker.signOrderAsync();
const secondOrderMakerAssetData = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address); const secondOrderMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const secondOrder = await maker.signOrderAsync({ const secondOrder = await maker.signOrderAsync({
makerAssetData: secondOrderMakerAssetData, makerAssetData: secondOrderMakerAssetData,
}); });
@ -245,7 +250,7 @@ blockchainTests('Forwarder integration tests', env => {
await testFactory.marketSellTestAsync(orders, 1.5); await testFactory.marketSellTestAsync(orders, 1.5);
}); });
it('should fail to fill an order with a fee denominated in an asset other than makerAsset or WETH', async () => { it('should fail to fill an order with a fee denominated in an asset other than makerAsset or WETH', async () => {
const takerFeeAssetData = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address); const takerFeeAssetData = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const order = await maker.signOrderAsync({ const order = await maker.signOrderAsync({
takerFeeAssetData, takerFeeAssetData,
takerFee: toBaseUnitAmount(1), takerFee: toBaseUnitAmount(1),
@ -336,7 +341,7 @@ blockchainTests('Forwarder integration tests', env => {
}); });
it('should buy exactly makerAssetBuyAmount in orders with different makerAssetData', async () => { it('should buy exactly makerAssetBuyAmount in orders with different makerAssetData', async () => {
const firstOrder = await maker.signOrderAsync(); const firstOrder = await maker.signOrderAsync();
const secondOrderMakerAssetData = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address); const secondOrderMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const secondOrder = await maker.signOrderAsync({ const secondOrder = await maker.signOrderAsync({
makerAssetData: secondOrderMakerAssetData, makerAssetData: secondOrderMakerAssetData,
}); });
@ -385,7 +390,7 @@ blockchainTests('Forwarder integration tests', env => {
it('should buy an ERC721 asset from a single order', async () => { it('should buy an ERC721 asset from a single order', async () => {
const erc721Order = await maker.signOrderAsync({ const erc721Order = await maker.signOrderAsync({
makerAssetAmount: new BigNumber(1), makerAssetAmount: new BigNumber(1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, nftId), makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, nftId),
takerFeeAssetData: wethAssetData, takerFeeAssetData: wethAssetData,
}); });
await testFactory.marketBuyTestAsync([erc721Order], 1); await testFactory.marketBuyTestAsync([erc721Order], 1);
@ -393,14 +398,14 @@ blockchainTests('Forwarder integration tests', env => {
it('should buy an ERC721 asset and pay a WETH fee', async () => { it('should buy an ERC721 asset and pay a WETH fee', async () => {
const erc721orderWithWethFee = await maker.signOrderAsync({ const erc721orderWithWethFee = await maker.signOrderAsync({
makerAssetAmount: new BigNumber(1), makerAssetAmount: new BigNumber(1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, nftId), makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, nftId),
takerFee: toBaseUnitAmount(1), takerFee: toBaseUnitAmount(1),
takerFeeAssetData: wethAssetData, takerFeeAssetData: wethAssetData,
}); });
await testFactory.marketBuyTestAsync([erc721orderWithWethFee], 1); await testFactory.marketBuyTestAsync([erc721orderWithWethFee], 1);
}); });
it('should fail to fill an order with a fee denominated in an asset other than makerAsset or WETH', async () => { it('should fail to fill an order with a fee denominated in an asset other than makerAsset or WETH', async () => {
const takerFeeAssetData = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address); const takerFeeAssetData = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const order = await maker.signOrderAsync({ const order = await maker.signOrderAsync({
takerFeeAssetData, takerFeeAssetData,
takerFee: toBaseUnitAmount(1), takerFee: toBaseUnitAmount(1),
@ -491,11 +496,21 @@ blockchainTests('Forwarder integration tests', env => {
); );
// Compute expected balances // Compute expected balances
const expectedBalances = LocalBalanceStore.create(balanceStore); const expectedBalances = LocalBalanceStore.create(devUtils, balanceStore);
expectedBalances.transferAsset(maker.address, taker.address, makerAssetFillAmount, makerAssetData); await expectedBalances.transferAssetAsync(
maker.address,
taker.address,
makerAssetFillAmount,
makerAssetData,
);
expectedBalances.wrapEth(taker.address, deployment.tokens.weth.address, ethValue); expectedBalances.wrapEth(taker.address, deployment.tokens.weth.address, ethValue);
expectedBalances.transferAsset(taker.address, maker.address, primaryTakerAssetFillAmount, wethAssetData); await expectedBalances.transferAssetAsync(
expectedBalances.transferAsset( taker.address,
maker.address,
primaryTakerAssetFillAmount,
wethAssetData,
);
await expectedBalances.transferAssetAsync(
taker.address, taker.address,
deployment.staking.stakingProxy.address, deployment.staking.stakingProxy.address,
DeploymentManager.protocolFee, DeploymentManager.protocolFee,
@ -537,15 +552,15 @@ blockchainTests('Forwarder integration tests', env => {
); );
// Compute expected balances // Compute expected balances
const expectedBalances = LocalBalanceStore.create(balanceStore); const expectedBalances = LocalBalanceStore.create(devUtils, balanceStore);
expectedBalances.transferAsset(maker.address, taker.address, makerAssetFillAmount, makerAssetData); expectedBalances.transferAssetAsync(maker.address, taker.address, makerAssetFillAmount, makerAssetData);
expectedBalances.wrapEth( expectedBalances.wrapEth(
taker.address, taker.address,
deployment.tokens.weth.address, deployment.tokens.weth.address,
takerAssetFillAmount.plus(DeploymentManager.protocolFee), takerAssetFillAmount.plus(DeploymentManager.protocolFee),
); );
expectedBalances.transferAsset(taker.address, maker.address, takerAssetFillAmount, wethAssetData); expectedBalances.transferAssetAsync(taker.address, maker.address, takerAssetFillAmount, wethAssetData);
expectedBalances.transferAsset( expectedBalances.transferAssetAsync(
taker.address, taker.address,
deployment.staking.stakingProxy.address, deployment.staking.stakingProxy.address,
DeploymentManager.protocolFee, DeploymentManager.protocolFee,

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { BlockchainBalanceStore, LocalBalanceStore } from '@0x/contracts-exchange'; import { BlockchainBalanceStore, LocalBalanceStore } from '@0x/contracts-exchange';
import { ForwarderContract } from '@0x/contracts-exchange-forwarder'; import { ForwarderContract } from '@0x/contracts-exchange-forwarder';
import { constants, expect, getPercentageOfValue, OrderStatus } from '@0x/contracts-test-utils'; import { constants, expect, getPercentageOfValue, OrderStatus } from '@0x/contracts-test-utils';
@ -33,6 +34,7 @@ export class ForwarderTestFactory {
private readonly _taker: Actor, private readonly _taker: Actor,
private readonly _orderFeeRecipient: FeeRecipient, private readonly _orderFeeRecipient: FeeRecipient,
private readonly _forwarderFeeRecipient: FeeRecipient, private readonly _forwarderFeeRecipient: FeeRecipient,
private readonly _devUtils: DevUtilsContract,
) {} ) {}
public async marketBuyTestAsync( public async marketBuyTestAsync(
@ -157,7 +159,7 @@ export class ForwarderTestFactory {
options: Partial<MarketBuyOptions>, options: Partial<MarketBuyOptions>,
): Promise<ForwarderFillState> { ): Promise<ForwarderFillState> {
await this._balanceStore.updateBalancesAsync(); await this._balanceStore.updateBalancesAsync();
const balances = LocalBalanceStore.create(this._balanceStore); const balances = LocalBalanceStore.create(this._devUtils, this._balanceStore);
const currentTotal = { const currentTotal = {
wethSpentAmount: constants.ZERO_AMOUNT, wethSpentAmount: constants.ZERO_AMOUNT,
makerAssetAcquiredAmount: constants.ZERO_AMOUNT, makerAssetAcquiredAmount: constants.ZERO_AMOUNT,
@ -173,7 +175,7 @@ export class ForwarderTestFactory {
continue; continue;
} }
const { wethSpentAmount, makerAssetAcquiredAmount } = this._simulateSingleFill( const { wethSpentAmount, makerAssetAcquiredAmount } = await this._simulateSingleFillAsync(
balances, balances,
order, order,
ordersInfoBefore[i].orderTakerAssetFilledAmount, ordersInfoBefore[i].orderTakerAssetFilledAmount,
@ -197,12 +199,12 @@ export class ForwarderTestFactory {
return { ...currentTotal, balances }; return { ...currentTotal, balances };
} }
private _simulateSingleFill( private async _simulateSingleFillAsync(
balances: LocalBalanceStore, balances: LocalBalanceStore,
order: SignedOrder, order: SignedOrder,
takerAssetFilled: BigNumber, takerAssetFilled: BigNumber,
fillFraction: number, fillFraction: number,
): ForwarderFillState { ): Promise<ForwarderFillState> {
let { makerAssetAmount, takerAssetAmount, makerFee, takerFee } = order; let { makerAssetAmount, takerAssetAmount, makerFee, takerFee } = order;
makerAssetAmount = makerAssetAmount.times(fillFraction).integerValue(BigNumber.ROUND_CEIL); makerAssetAmount = makerAssetAmount.times(fillFraction).integerValue(BigNumber.ROUND_CEIL);
takerAssetAmount = takerAssetAmount.times(fillFraction).integerValue(BigNumber.ROUND_CEIL); takerAssetAmount = takerAssetAmount.times(fillFraction).integerValue(BigNumber.ROUND_CEIL);
@ -236,27 +238,42 @@ export class ForwarderTestFactory {
// (In reality this is done all at once, but we simulate it order by order) // (In reality this is done all at once, but we simulate it order by order)
// Maker -> Forwarder // Maker -> Forwarder
balances.transferAsset(this._maker.address, this._forwarder.address, makerAssetAmount, order.makerAssetData); await balances.transferAssetAsync(
this._maker.address,
this._forwarder.address,
makerAssetAmount,
order.makerAssetData,
);
// Maker -> Order fee recipient // Maker -> Order fee recipient
balances.transferAsset(this._maker.address, this._orderFeeRecipient.address, makerFee, order.makerFeeAssetData); await balances.transferAssetAsync(
this._maker.address,
this._orderFeeRecipient.address,
makerFee,
order.makerFeeAssetData,
);
// Forwarder -> Maker // Forwarder -> Maker
balances.transferAsset(this._forwarder.address, this._maker.address, takerAssetAmount, order.takerAssetData); await balances.transferAssetAsync(
this._forwarder.address,
this._maker.address,
takerAssetAmount,
order.takerAssetData,
);
// Forwarder -> Order fee recipient // Forwarder -> Order fee recipient
balances.transferAsset( await balances.transferAssetAsync(
this._forwarder.address, this._forwarder.address,
this._orderFeeRecipient.address, this._orderFeeRecipient.address,
takerFee, takerFee,
order.takerFeeAssetData, order.takerFeeAssetData,
); );
// Forwarder pays the protocol fee in WETH // Forwarder pays the protocol fee in WETH
balances.transferAsset( await balances.transferAssetAsync(
this._forwarder.address, this._forwarder.address,
this._deployment.staking.stakingProxy.address, this._deployment.staking.stakingProxy.address,
DeploymentManager.protocolFee, DeploymentManager.protocolFee,
order.takerAssetData, order.takerAssetData,
); );
// Forwarder gives acquired maker asset to taker // Forwarder gives acquired maker asset to taker
balances.transferAsset( await balances.transferAssetAsync(
this._forwarder.address, this._forwarder.address,
this._taker.address, this._taker.address,
makerAssetAcquiredAmount, makerAssetAcquiredAmount,

View File

@ -1,4 +1,5 @@
import { artifacts as assetProxyArtifacts } from '@0x/contracts-asset-proxy'; import { artifacts as assetProxyArtifacts } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { IERC20TokenEvents, IERC20TokenTransferEventArgs } from '@0x/contracts-erc20'; import { IERC20TokenEvents, IERC20TokenTransferEventArgs } from '@0x/contracts-erc20';
import { import {
artifacts as exchangeArtifacts, artifacts as exchangeArtifacts,
@ -16,11 +17,12 @@ import {
expect, expect,
getLatestBlockTimestampAsync, getLatestBlockTimestampAsync,
Numberish, Numberish,
provider,
toBaseUnitAmount, toBaseUnitAmount,
TransactionHelper, TransactionHelper,
verifyEvents, verifyEvents,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { assetDataUtils, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils'; import { ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
import { FillResults, OrderStatus, SignedOrder } from '@0x/types'; import { FillResults, OrderStatus, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -32,6 +34,7 @@ import { DeploymentManager } from '../utils/deployment_manager';
const { addFillResults, safeGetPartialAmountFloor } = ReferenceFunctions; const { addFillResults, safeGetPartialAmountFloor } = ReferenceFunctions;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
// tslint:disable:no-unnecessary-type-assertion // tslint:disable:no-unnecessary-type-assertion
blockchainTests.resets('Exchange wrappers', env => { blockchainTests.resets('Exchange wrappers', env => {
let maker: Maker; let maker: Maker;
@ -67,10 +70,10 @@ blockchainTests.resets('Exchange wrappers', env => {
name: 'market maker', name: 'market maker',
deployment, deployment,
orderConfig: { orderConfig: {
makerAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[0].address), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.erc20[0].address),
takerAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[1].address), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.erc20[1].address),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.erc20[2].address),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address), takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.erc20[2].address),
feeRecipientAddress: feeRecipient, feeRecipientAddress: feeRecipient,
}, },
}); });
@ -106,9 +109,9 @@ blockchainTests.resets('Exchange wrappers', env => {
await blockchainBalances.updateBalancesAsync(); await blockchainBalances.updateBalancesAsync();
initialLocalBalances = LocalBalanceStore.create(blockchainBalances); initialLocalBalances = LocalBalanceStore.create(devUtils, blockchainBalances);
wethAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.weth.address); wethAssetData = await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.weth.address);
txHelper = new TransactionHelper(env.web3Wrapper, { txHelper = new TransactionHelper(env.web3Wrapper, {
...assetProxyArtifacts, ...assetProxyArtifacts,
@ -118,7 +121,7 @@ blockchainTests.resets('Exchange wrappers', env => {
}); });
beforeEach(async () => { beforeEach(async () => {
localBalances = LocalBalanceStore.create(initialLocalBalances); localBalances = LocalBalanceStore.create(devUtils, initialLocalBalances);
}); });
interface SignedOrderWithValidity { interface SignedOrderWithValidity {
@ -126,9 +129,13 @@ blockchainTests.resets('Exchange wrappers', env => {
isValid: boolean; isValid: boolean;
} }
function simulateFill(signedOrder: SignedOrder, expectedFillResults: FillResults, shouldUseWeth: boolean): void { async function simulateFillAsync(
signedOrder: SignedOrder,
expectedFillResults: FillResults,
shouldUseWeth: boolean,
): Promise<void> {
// taker -> maker // taker -> maker
localBalances.transferAsset( await localBalances.transferAssetAsync(
taker.address, taker.address,
maker.address, maker.address,
expectedFillResults.takerAssetFilledAmount, expectedFillResults.takerAssetFilledAmount,
@ -136,7 +143,7 @@ blockchainTests.resets('Exchange wrappers', env => {
); );
// maker -> taker // maker -> taker
localBalances.transferAsset( await localBalances.transferAssetAsync(
maker.address, maker.address,
taker.address, taker.address,
expectedFillResults.makerAssetFilledAmount, expectedFillResults.makerAssetFilledAmount,
@ -144,7 +151,7 @@ blockchainTests.resets('Exchange wrappers', env => {
); );
// maker -> feeRecipient // maker -> feeRecipient
localBalances.transferAsset( await localBalances.transferAssetAsync(
maker.address, maker.address,
feeRecipient, feeRecipient,
expectedFillResults.makerFeePaid, expectedFillResults.makerFeePaid,
@ -152,7 +159,7 @@ blockchainTests.resets('Exchange wrappers', env => {
); );
// taker -> feeRecipient // taker -> feeRecipient
localBalances.transferAsset( await localBalances.transferAssetAsync(
taker.address, taker.address,
feeRecipient, feeRecipient,
expectedFillResults.takerFeePaid, expectedFillResults.takerFeePaid,
@ -161,7 +168,7 @@ blockchainTests.resets('Exchange wrappers', env => {
// taker -> protocol fees // taker -> protocol fees
if (shouldUseWeth) { if (shouldUseWeth) {
localBalances.transferAsset( await localBalances.transferAssetAsync(
taker.address, taker.address,
deployment.staking.stakingProxy.address, deployment.staking.stakingProxy.address,
expectedFillResults.protocolFeePaid, expectedFillResults.protocolFeePaid,
@ -332,7 +339,7 @@ blockchainTests.resets('Exchange wrappers', env => {
const shouldPayWethFees = DeploymentManager.protocolFee.gt(value); const shouldPayWethFees = DeploymentManager.protocolFee.gt(value);
// Simulate filling the order // Simulate filling the order
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees); await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
// Ensure that the correct logs were emitted and that the balances are accurate. // Ensure that the correct logs were emitted and that the balances are accurate.
await assertResultsAsync(receipt, [{ signedOrder, expectedFillResults, shouldPayWethFees }]); await assertResultsAsync(receipt, [{ signedOrder, expectedFillResults, shouldPayWethFees }]);
@ -430,7 +437,7 @@ blockchainTests.resets('Exchange wrappers', env => {
} }
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees }); fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees); await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
} }
const [fillResults, receipt] = await txHelper.getResultAndReceiptAsync( const [fillResults, receipt] = await txHelper.getResultAndReceiptAsync(
@ -492,7 +499,7 @@ blockchainTests.resets('Exchange wrappers', env => {
} }
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees }); fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees); await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
} }
const [fillResults, receipt] = await txHelper.getResultAndReceiptAsync( const [fillResults, receipt] = await txHelper.getResultAndReceiptAsync(
@ -583,7 +590,7 @@ blockchainTests.resets('Exchange wrappers', env => {
} }
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees }); fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees); await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
} else { } else {
totalFillResults.push(nullFillResults); totalFillResults.push(nullFillResults);
} }
@ -696,7 +703,7 @@ blockchainTests.resets('Exchange wrappers', env => {
takerFillAmount, takerFillAmount,
); );
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees); await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees }); fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
totalFillResults = addFillResults(totalFillResults, expectedFillResults); totalFillResults = addFillResults(totalFillResults, expectedFillResults);
@ -774,7 +781,9 @@ blockchainTests.resets('Exchange wrappers', env => {
}); });
it('should fill a signedOrder that does not use the same takerAssetAddress (eth protocol fee)', async () => { it('should fill a signedOrder that does not use the same takerAssetAddress (eth protocol fee)', async () => {
const differentTakerAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address); const differentTakerAssetData = await devUtils.encodeERC20AssetData.callAsync(
deployment.tokens.erc20[2].address,
);
signedOrders = [ signedOrders = [
await maker.signOrderAsync(), await maker.signOrderAsync(),
@ -795,7 +804,9 @@ blockchainTests.resets('Exchange wrappers', env => {
}); });
it('should fill a signedOrder that does not use the same takerAssetAddress (weth protocol fee)', async () => { it('should fill a signedOrder that does not use the same takerAssetAddress (weth protocol fee)', async () => {
const differentTakerAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address); const differentTakerAssetData = await devUtils.encodeERC20AssetData.callAsync(
deployment.tokens.erc20[2].address,
);
signedOrders = [ signedOrders = [
await maker.signOrderAsync(), await maker.signOrderAsync(),
@ -890,7 +901,7 @@ blockchainTests.resets('Exchange wrappers', env => {
makerAssetBought, makerAssetBought,
); );
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees); await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees }); fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
totalFillResults = addFillResults(totalFillResults, expectedFillResults); totalFillResults = addFillResults(totalFillResults, expectedFillResults);
@ -968,7 +979,9 @@ blockchainTests.resets('Exchange wrappers', env => {
}); });
it('should fill a signedOrder that does not use the same makerAssetAddress (eth protocol fee)', async () => { it('should fill a signedOrder that does not use the same makerAssetAddress (eth protocol fee)', async () => {
const differentMakerAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address); const differentMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(
deployment.tokens.erc20[2].address,
);
signedOrders = [ signedOrders = [
await maker.signOrderAsync(), await maker.signOrderAsync(),
@ -990,7 +1003,9 @@ blockchainTests.resets('Exchange wrappers', env => {
}); });
it('should fill a signedOrder that does not use the same makerAssetAddress (weth protocol fee)', async () => { it('should fill a signedOrder that does not use the same makerAssetAddress (weth protocol fee)', async () => {
const differentMakerAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address); const differentMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(
deployment.tokens.erc20[2].address,
);
signedOrders = [ signedOrders = [
await maker.signOrderAsync(), await maker.signOrderAsync(),

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { IERC20TokenEvents, IERC20TokenTransferEventArgs } from '@0x/contracts-erc20'; import { IERC20TokenEvents, IERC20TokenTransferEventArgs } from '@0x/contracts-erc20';
import { import {
BlockchainBalanceStore, BlockchainBalanceStore,
@ -13,8 +14,8 @@ import {
IStakingEventsRewardsPaidEventArgs, IStakingEventsRewardsPaidEventArgs,
IStakingEventsStakingPoolEarnedRewardsInEpochEventArgs, IStakingEventsStakingPoolEarnedRewardsInEpochEventArgs,
} from '@0x/contracts-staking'; } from '@0x/contracts-staking';
import { blockchainTests, constants, expect, toBaseUnitAmount, verifyEvents } from '@0x/contracts-test-utils'; import { blockchainTests, constants, expect, provider, toBaseUnitAmount, verifyEvents } from '@0x/contracts-test-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { orderHashUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types'; import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -22,6 +23,7 @@ import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { actorAddressesByName, FeeRecipient, Maker, OperatorStakerMaker, StakerKeeper, Taker } from '../actors'; import { actorAddressesByName, FeeRecipient, Maker, OperatorStakerMaker, StakerKeeper, Taker } from '../actors';
import { DeploymentManager } from '../utils/deployment_manager'; import { DeploymentManager } from '../utils/deployment_manager';
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
blockchainTests.resets('fillOrder integration tests', env => { blockchainTests.resets('fillOrder integration tests', env => {
let deployment: DeploymentManager; let deployment: DeploymentManager;
let balanceStore: BlockchainBalanceStore; let balanceStore: BlockchainBalanceStore;
@ -48,10 +50,10 @@ blockchainTests.resets('fillOrder integration tests', env => {
}); });
const orderConfig = { const orderConfig = {
feeRecipientAddress: feeRecipient.address, feeRecipientAddress: feeRecipient.address,
makerAssetData: assetDataUtils.encodeERC20AssetData(makerToken.address), makerAssetData: await devUtils.encodeERC20AssetData.callAsync(makerToken.address),
takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken.address), takerAssetData: await devUtils.encodeERC20AssetData.callAsync(takerToken.address),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerToken.address), makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(makerToken.address),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(takerToken.address), takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(takerToken.address),
makerFee: constants.ZERO_AMOUNT, makerFee: constants.ZERO_AMOUNT,
takerFee: constants.ZERO_AMOUNT, takerFee: constants.ZERO_AMOUNT,
}; };
@ -93,20 +95,30 @@ blockchainTests.resets('fillOrder integration tests', env => {
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
}); });
function simulateFill( async function simulateFillAsync(
order: SignedOrder, order: SignedOrder,
txReceipt: TransactionReceiptWithDecodedLogs, txReceipt: TransactionReceiptWithDecodedLogs,
msgValue?: BigNumber, msgValue?: BigNumber,
): LocalBalanceStore { ): Promise<LocalBalanceStore> {
let remainingValue = msgValue !== undefined ? msgValue : DeploymentManager.protocolFee; let remainingValue = msgValue !== undefined ? msgValue : DeploymentManager.protocolFee;
const localBalanceStore = LocalBalanceStore.create(balanceStore); const localBalanceStore = LocalBalanceStore.create(devUtils, balanceStore);
// Transaction gas cost // Transaction gas cost
localBalanceStore.burnGas(txReceipt.from, DeploymentManager.gasPrice.times(txReceipt.gasUsed)); localBalanceStore.burnGas(txReceipt.from, DeploymentManager.gasPrice.times(txReceipt.gasUsed));
// Taker -> Maker // Taker -> Maker
localBalanceStore.transferAsset(taker.address, maker.address, order.takerAssetAmount, order.takerAssetData); await localBalanceStore.transferAssetAsync(
taker.address,
maker.address,
order.takerAssetAmount,
order.takerAssetData,
);
// Maker -> Taker // Maker -> Taker
localBalanceStore.transferAsset(maker.address, taker.address, order.makerAssetAmount, order.makerAssetData); await localBalanceStore.transferAssetAsync(
maker.address,
taker.address,
order.makerAssetAmount,
order.makerAssetData,
);
// Protocol fee // Protocol fee
if (remainingValue.isGreaterThanOrEqualTo(DeploymentManager.protocolFee)) { if (remainingValue.isGreaterThanOrEqualTo(DeploymentManager.protocolFee)) {
@ -117,11 +129,11 @@ blockchainTests.resets('fillOrder integration tests', env => {
); );
remainingValue = remainingValue.minus(DeploymentManager.protocolFee); remainingValue = remainingValue.minus(DeploymentManager.protocolFee);
} else { } else {
localBalanceStore.transferAsset( await localBalanceStore.transferAssetAsync(
taker.address, taker.address,
deployment.staking.stakingProxy.address, deployment.staking.stakingProxy.address,
DeploymentManager.protocolFee, DeploymentManager.protocolFee,
assetDataUtils.encodeERC20AssetData(deployment.tokens.weth.address), await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.weth.address),
); );
} }
@ -178,7 +190,7 @@ blockchainTests.resets('fillOrder integration tests', env => {
const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount); const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount);
// Check balances // Check balances
const expectedBalances = simulateFill(order, receipt); const expectedBalances = await simulateFillAsync(order, receipt);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
@ -204,7 +216,7 @@ blockchainTests.resets('fillOrder integration tests', env => {
const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount); const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount);
// Check balances // Check balances
const expectedBalances = simulateFill(order, receipt); const expectedBalances = await simulateFillAsync(order, receipt);
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances); balanceStore.assertEquals(expectedBalances);
@ -237,7 +249,7 @@ blockchainTests.resets('fillOrder integration tests', env => {
// Fetch the current balances // Fetch the current balances
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
const expectedBalances = LocalBalanceStore.create(balanceStore); const expectedBalances = LocalBalanceStore.create(devUtils, balanceStore);
// End the epoch. This should wrap the staking proxy's ETH balance. // End the epoch. This should wrap the staking proxy's ETH balance.
const endEpochReceipt = await delegator.endEpochAsync(); const endEpochReceipt = await delegator.endEpochAsync();
@ -279,11 +291,11 @@ blockchainTests.resets('fillOrder integration tests', env => {
const [finalizePoolReceipt] = await delegator.finalizePoolsAsync([poolId]); const [finalizePoolReceipt] = await delegator.finalizePoolsAsync([poolId]);
// Check balances // Check balances
expectedBalances.transferAsset( await expectedBalances.transferAssetAsync(
deployment.staking.stakingProxy.address, deployment.staking.stakingProxy.address,
operator.address, operator.address,
operatorReward, operatorReward,
assetDataUtils.encodeERC20AssetData(deployment.tokens.weth.address), await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.weth.address),
); );
expectedBalances.burnGas(delegator.address, DeploymentManager.gasPrice.times(finalizePoolReceipt.gasUsed)); expectedBalances.burnGas(delegator.address, DeploymentManager.gasPrice.times(finalizePoolReceipt.gasUsed));
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();
@ -340,7 +352,7 @@ blockchainTests.resets('fillOrder integration tests', env => {
const order = await maker.signOrderAsync(); const order = await maker.signOrderAsync();
const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount, { value: constants.ZERO_AMOUNT }); const receipt = await taker.fillOrderAsync(order, order.takerAssetAmount, { value: constants.ZERO_AMOUNT });
const rewardsAvailable = DeploymentManager.protocolFee; const rewardsAvailable = DeploymentManager.protocolFee;
const expectedBalances = simulateFill(order, receipt, constants.ZERO_AMOUNT); const expectedBalances = await simulateFillAsync(order, receipt, constants.ZERO_AMOUNT);
// End the epoch. This should wrap the staking proxy's ETH balance. // End the epoch. This should wrap the staking proxy's ETH balance.
const endEpochReceipt = await delegator.endEpochAsync(); const endEpochReceipt = await delegator.endEpochAsync();
@ -359,11 +371,11 @@ blockchainTests.resets('fillOrder integration tests', env => {
const [finalizePoolReceipt] = await delegator.finalizePoolsAsync([poolId]); const [finalizePoolReceipt] = await delegator.finalizePoolsAsync([poolId]);
// Check balances // Check balances
expectedBalances.transferAsset( await expectedBalances.transferAssetAsync(
deployment.staking.stakingProxy.address, deployment.staking.stakingProxy.address,
operator.address, operator.address,
operatorReward, operatorReward,
assetDataUtils.encodeERC20AssetData(deployment.tokens.weth.address), await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.weth.address),
); );
expectedBalances.burnGas(delegator.address, DeploymentManager.gasPrice.times(finalizePoolReceipt.gasUsed)); expectedBalances.burnGas(delegator.address, DeploymentManager.gasPrice.times(finalizePoolReceipt.gasUsed));
await balanceStore.updateBalancesAsync(); await balanceStore.updateBalancesAsync();

View File

@ -50,6 +50,7 @@
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md", "homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": { "devDependencies": {
"@0x/abi-gen": "^4.3.0-beta.0", "@0x/abi-gen": "^4.3.0-beta.0",
"@0x/contracts-dev-utils": "^0.1.0-beta.0",
"@0x/contracts-exchange-libs": "^3.1.0-beta.0", "@0x/contracts-exchange-libs": "^3.1.0-beta.0",
"@0x/contracts-gen": "^1.1.0-beta.0", "@0x/contracts-gen": "^1.1.0-beta.0",
"@0x/contracts-test-utils": "^3.2.0-beta.0", "@0x/contracts-test-utils": "^3.2.0-beta.0",

View File

@ -1,12 +1,14 @@
import { ERC20Wrapper } from '@0x/contracts-asset-proxy'; import { ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { import {
blockchainTests, blockchainTests,
constants, constants,
expect, expect,
expectTransactionFailedAsync, expectTransactionFailedAsync,
filterLogsToArguments, filterLogsToArguments,
provider,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { assetDataUtils, StakingRevertErrors } from '@0x/order-utils'; import { StakingRevertErrors } from '@0x/order-utils';
import { RevertReason } from '@0x/types'; import { RevertReason } from '@0x/types';
import { AuthorizableRevertErrors, BigNumber, SafeMathRevertErrors } from '@0x/utils'; import { AuthorizableRevertErrors, BigNumber, SafeMathRevertErrors } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -32,6 +34,8 @@ blockchainTests.resets('ZrxVault unit tests', env => {
let zrxAssetData: string; let zrxAssetData: string;
let zrxProxyAddress: string; let zrxProxyAddress: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
before(async () => { before(async () => {
// create accounts // create accounts
accounts = await env.getAccountAddressesAsync(); accounts = await env.getAccountAddressesAsync();
@ -44,7 +48,7 @@ blockchainTests.resets('ZrxVault unit tests', env => {
zrxProxyAddress = erc20ProxyContract.address; zrxProxyAddress = erc20ProxyContract.address;
// deploy zrx token // deploy zrx token
const [zrxTokenContract] = await erc20Wrapper.deployDummyTokensAsync(1, constants.DUMMY_TOKEN_DECIMALS); const [zrxTokenContract] = await erc20Wrapper.deployDummyTokensAsync(1, constants.DUMMY_TOKEN_DECIMALS);
zrxAssetData = assetDataUtils.encodeERC20AssetData(zrxTokenContract.address); zrxAssetData = await devUtils.encodeERC20AssetData.callAsync(zrxTokenContract.address);
await erc20Wrapper.setBalancesAndAllowancesAsync(); await erc20Wrapper.setBalancesAndAllowancesAsync();

View File

@ -1,4 +1,13 @@
[ [
{
"version": "3.2.0-beta.1",
"changes": [
{
"note": "OrderFactory default order expiration time increased from ten minutes to fifteen minutes ",
"pr": 2304
}
]
},
{ {
"version": "3.2.0-beta.0", "version": "3.2.0-beta.0",
"changes": [ "changes": [

View File

@ -19,12 +19,12 @@ export class OrderFactory {
customOrderParams: Partial<Order> = {}, customOrderParams: Partial<Order> = {},
signatureType: SignatureType = SignatureType.EthSign, signatureType: SignatureType = SignatureType.EthSign,
): Promise<SignedOrder> { ): Promise<SignedOrder> {
const tenMinutesInSeconds = 10 * 60; const fifteenMinutesInSeconds = 15 * 60;
const currentBlockTimestamp = await getLatestBlockTimestampAsync(); const currentBlockTimestamp = await getLatestBlockTimestampAsync();
const order = ({ const order = ({
takerAddress: constants.NULL_ADDRESS, takerAddress: constants.NULL_ADDRESS,
senderAddress: constants.NULL_ADDRESS, senderAddress: constants.NULL_ADDRESS,
expirationTimeSeconds: new BigNumber(currentBlockTimestamp).plus(tenMinutesInSeconds), expirationTimeSeconds: new BigNumber(currentBlockTimestamp).plus(fifteenMinutesInSeconds),
salt: generatePseudoRandomSalt(), salt: generatePseudoRandomSalt(),
...this._defaultOrderParams, ...this._defaultOrderParams,
...customOrderParams, ...customOrderParams,

View File

@ -1,5 +1,6 @@
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
import * as crypto from 'crypto';
import { import {
artifacts as proxyArtifacts, artifacts as proxyArtifacts,
@ -20,12 +21,12 @@ import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/cont
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange'; import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
import { chaiSetup, constants, LogDecoder, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils'; import { chaiSetup, constants, LogDecoder, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId } from '@0x/types'; import { AssetProxyId } from '@0x/types';
import { BigNumber, providerUtils } from '@0x/utils'; import { BigNumber, providerUtils, StringRevertError } from '@0x/utils';
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
import { artifacts, LibAssetDataContract } from '@0x/contracts-dev-utils'; import { artifacts, LibAssetDataContract } from '@0x/contracts-dev-utils';
import { InvalidByteOperationError } from '@0x/utils/lib/src/lib_bytes_revert_errors';
chaiSetup.configure(); chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
@ -61,6 +62,13 @@ const KNOWN_MULTI_ASSET_ENCODING = {
assetData: assetData:
'0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
}; };
const KNOWN_STATIC_CALL_ENCODING = {
staticCallTargetAddress: '0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f',
staticCallData: '0xed2cfc9c0000000000000000000000000000000000000000000000000000000000000001',
expectedReturnDataHash: '0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6',
assetData:
'0xc339d10a0000000000000000000000006dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f0000000000000000000000000000000000000000000000000000000000000060b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60000000000000000000000000000000000000000000000000000000000000024ed2cfc9c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
};
describe('LibAssetData', () => { describe('LibAssetData', () => {
let exchange: ExchangeContract; let exchange: ExchangeContract;
@ -215,6 +223,18 @@ describe('LibAssetData', () => {
}); });
describe('encoding and decoding', () => { describe('encoding and decoding', () => {
it('should decode any asset proxy ID', async () => {
const assetDataScenarios = [
[KNOWN_ERC20_ENCODING.assetData, AssetProxyId.ERC20],
[KNOWN_ERC721_ENCODING.assetData, AssetProxyId.ERC721],
[KNOWN_ERC1155_ENCODING.assetData, AssetProxyId.ERC1155],
[KNOWN_MULTI_ASSET_ENCODING.assetData, AssetProxyId.MultiAsset],
];
for (const [assetData, proxyId] of assetDataScenarios) {
expect(await libAssetData.decodeAssetProxyId.callAsync(assetData)).to.equal(proxyId);
}
});
it('should encode ERC20 asset data', async () => { it('should encode ERC20 asset data', async () => {
expect(await libAssetData.encodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.address)).to.equal( expect(await libAssetData.encodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.address)).to.equal(
KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC20_ENCODING.assetData,
@ -286,35 +306,97 @@ describe('LibAssetData', () => {
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData, KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
]); ]);
}); });
it('should encode StaticCall data', async () => {
expect(
await libAssetData.encodeStaticCallAssetData.callAsync(
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
KNOWN_STATIC_CALL_ENCODING.staticCallData,
KNOWN_STATIC_CALL_ENCODING.expectedReturnDataHash,
),
).to.equal(KNOWN_STATIC_CALL_ENCODING.assetData);
});
it('should decode StaticCall data', async () => {
expect(
await libAssetData.decodeStaticCallAssetData.callAsync(KNOWN_STATIC_CALL_ENCODING.assetData),
).to.deep.equal([
AssetProxyId.StaticCall,
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
KNOWN_STATIC_CALL_ENCODING.staticCallData,
KNOWN_STATIC_CALL_ENCODING.expectedReturnDataHash,
]);
});
});
describe('revertIfInvalidAssetData', async () => {
it('should succeed for any valid asset data', async () => {
const assetData = [
KNOWN_ERC20_ENCODING.assetData,
KNOWN_ERC721_ENCODING.assetData,
KNOWN_ERC1155_ENCODING.assetData,
KNOWN_MULTI_ASSET_ENCODING.assetData,
KNOWN_STATIC_CALL_ENCODING.assetData,
];
for (const data of assetData) {
await libAssetData.revertIfInvalidAssetData.callAsync(data);
}
return;
});
it('should revert for invalid assetProxyId', async () => {
const badAssetData = '0x' + crypto.randomBytes(4).toString('hex') + constants.NULL_ADDRESS;
await expect(libAssetData.revertIfInvalidAssetData.callAsync(badAssetData)).to.eventually.be.rejectedWith(
StringRevertError,
);
});
it('should revert for invalid assetData with valid assetProxyId', async () => {
// the other encodings are always valid if the assetProxyId is valid
const assetData = [KNOWN_ERC20_ENCODING.assetData, KNOWN_ERC721_ENCODING.assetData];
for (const data of assetData) {
const badData = data.substring(0, data.length - 2); // drop one byte but retain assetProxyId
await expect(libAssetData.revertIfInvalidAssetData.callAsync(badData)).to.eventually.be.rejectedWith(
InvalidByteOperationError,
);
}
});
}); });
describe('getBalance', () => { describe('getBalance', () => {
it('should query ERC20 balance by asset data', async () => { it('should query ERC20 balance by asset data', async () => {
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address); const assetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal( expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(
erc20TokenTotalSupply, erc20TokenTotalSupply,
); );
}); });
it('should return 0 if ERC20 token does not exist', async () => { it('should return 0 if ERC20 token does not exist', async () => {
const assetData = assetDataUtils.encodeERC20AssetData(constants.NULL_ADDRESS); const assetData = await libAssetData.encodeERC20AssetData.callAsync(constants.NULL_ADDRESS);
const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData); const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT); expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
}); });
it('should query ERC721 balance by asset data', async () => { it('should query ERC721 balance by asset data', async () => {
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId); const assetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(1); expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(1);
}); });
it('should return 0 if ERC721 token does not exist', async () => { it('should return 0 if ERC721 token does not exist', async () => {
const assetData = assetDataUtils.encodeERC721AssetData(constants.NULL_ADDRESS, firstERC721TokenId); const assetData = await libAssetData.encodeERC721AssetData.callAsync(
constants.NULL_ADDRESS,
firstERC721TokenId,
);
const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData); const balance = await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData);
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT); expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
}); });
it('should query ERC1155 balances by asset data', async () => { it('should query ERC1155 balances by asset data', async () => {
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await libAssetData.encodeERC1155AssetData.callAsync(
erc1155Token.address, erc1155Token.address,
[erc1155TokenId], [erc1155TokenId],
[new BigNumber(1)], [new BigNumber(1)],
@ -324,7 +406,7 @@ describe('LibAssetData', () => {
}); });
it('should return 0 if ERC1155 token does not exist', async () => { it('should return 0 if ERC1155 token does not exist', async () => {
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await libAssetData.encodeERC1155AssetData.callAsync(
constants.NULL_ADDRESS, constants.NULL_ADDRESS,
[erc1155TokenId], [erc1155TokenId],
[new BigNumber(1)], [new BigNumber(1)],
@ -335,11 +417,11 @@ describe('LibAssetData', () => {
}); });
it('should query multi-asset batch balance by asset data', async () => { it('should query multi-asset batch balance by asset data', async () => {
const assetData = assetDataUtils.encodeMultiAssetData( const assetData = await libAssetData.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)], [new BigNumber(1), new BigNumber(1)],
[ [
assetDataUtils.encodeERC20AssetData(erc20Token.address), await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address),
assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId), await libAssetData.encodeERC721AssetData.callAsync(erc721Token.address, firstERC721TokenId),
], ],
); );
expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal( expect(await libAssetData.getBalance.callAsync(tokenOwnerAddress, assetData)).to.bignumber.equal(
@ -357,7 +439,7 @@ describe('LibAssetData', () => {
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1)); const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(1));
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001'); const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer)); const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await libAssetData.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -370,7 +452,7 @@ describe('LibAssetData', () => {
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0)); const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0));
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001'); const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer)); const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await libAssetData.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
expectedResultHash, expectedResultHash,
@ -386,7 +468,7 @@ describe('LibAssetData', () => {
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, { await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
from: tokenOwnerAddress, from: tokenOwnerAddress,
}); });
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address); const assetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
expect( expect(
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData), await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
).to.bignumber.equal(allowance); ).to.bignumber.equal(allowance);
@ -396,7 +478,10 @@ describe('LibAssetData', () => {
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, { await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
from: tokenOwnerAddress, from: tokenOwnerAddress,
}); });
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId); const assetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect( expect(
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData), await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
).to.bignumber.equal(1); ).to.bignumber.equal(1);
@ -406,7 +491,10 @@ describe('LibAssetData', () => {
await erc721Token.setApprovalForAll.awaitTransactionSuccessAsync(erc721Proxy.address, true, { await erc721Token.setApprovalForAll.awaitTransactionSuccessAsync(erc721Proxy.address, true, {
from: tokenOwnerAddress, from: tokenOwnerAddress,
}); });
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId); const assetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect( expect(
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData), await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); ).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
@ -416,7 +504,7 @@ describe('LibAssetData', () => {
await erc1155Token.setApprovalForAll.awaitTransactionSuccessAsync(erc1155Proxy.address, true, { await erc1155Token.setApprovalForAll.awaitTransactionSuccessAsync(erc1155Proxy.address, true, {
from: tokenOwnerAddress, from: tokenOwnerAddress,
}); });
const assetData = assetDataUtils.encodeERC1155AssetData( const assetData = await libAssetData.encodeERC1155AssetData.callAsync(
erc1155Token.address, erc1155Token.address,
[erc1155TokenId], [erc1155TokenId],
[new BigNumber(1)], [new BigNumber(1)],
@ -435,11 +523,11 @@ describe('LibAssetData', () => {
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, { await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
from: tokenOwnerAddress, from: tokenOwnerAddress,
}); });
const assetData = assetDataUtils.encodeMultiAssetData( const assetData = await libAssetData.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)], [new BigNumber(1), new BigNumber(1)],
[ [
assetDataUtils.encodeERC20AssetData(erc20Token.address), await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address),
assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId), await libAssetData.encodeERC721AssetData.callAsync(erc721Token.address, firstERC721TokenId),
], ],
); );
expect( expect(
@ -456,7 +544,7 @@ describe('LibAssetData', () => {
it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => { it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
const staticCallData = AssetProxyId.StaticCall; const staticCallData = AssetProxyId.StaticCall;
const assetData = assetDataUtils.encodeStaticCallAssetData( const assetData = await libAssetData.encodeStaticCallAssetData.callAsync(
staticCallTarget.address, staticCallTarget.address,
staticCallData, staticCallData,
constants.KECCAK256_NULL, constants.KECCAK256_NULL,
@ -468,8 +556,11 @@ describe('LibAssetData', () => {
describe('getBatchBalances', () => { describe('getBatchBalances', () => {
it('should query balances for a batch of asset data strings', async () => { it('should query balances for a batch of asset data strings', async () => {
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address); const erc20AssetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId); const erc721AssetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect( expect(
await libAssetData.getBatchBalances.callAsync(tokenOwnerAddress, [erc20AssetData, erc721AssetData]), await libAssetData.getBatchBalances.callAsync(tokenOwnerAddress, [erc20AssetData, erc721AssetData]),
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]); ).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
@ -482,7 +573,7 @@ describe('LibAssetData', () => {
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, { await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
from: tokenOwnerAddress, from: tokenOwnerAddress,
}); });
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address); const assetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
expect( expect(
await libAssetData.getBalanceAndAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData), await libAssetData.getBalanceAndAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), allowance]); ).to.deep.equal([new BigNumber(erc20TokenTotalSupply), allowance]);
@ -494,7 +585,7 @@ describe('LibAssetData', () => {
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, { await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
from: tokenOwnerAddress, from: tokenOwnerAddress,
}); });
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address); const assetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
expect( expect(
await libAssetData.getBatchBalancesAndAssetProxyAllowances.callAsync(tokenOwnerAddress, [assetData]), await libAssetData.getBatchBalancesAndAssetProxyAllowances.callAsync(tokenOwnerAddress, [assetData]),
).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [allowance]]); ).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [allowance]]);
@ -510,8 +601,11 @@ describe('LibAssetData', () => {
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, { await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
from: tokenOwnerAddress, from: tokenOwnerAddress,
}); });
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address); const erc20AssetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId); const erc721AssetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect( expect(
await libAssetData.getBatchAssetProxyAllowances.callAsync(tokenOwnerAddress, [ await libAssetData.getBatchAssetProxyAllowances.callAsync(tokenOwnerAddress, [
erc20AssetData, erc20AssetData,

View File

@ -19,7 +19,7 @@ import {
web3Wrapper, web3Wrapper,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils, orderHashUtils } from '@0x/order-utils'; import { orderHashUtils } from '@0x/order-utils';
import { OrderTransferResults, SignedOrder } from '@0x/types'; import { OrderTransferResults, SignedOrder } from '@0x/types';
import { BigNumber, providerUtils } from '@0x/utils'; import { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -79,7 +79,6 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync(); [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
erc721Proxy = await erc721Wrapper.deployProxyAsync(); erc721Proxy = await erc721Wrapper.deployProxyAsync();
feeAssetData = assetDataUtils.encodeERC20AssetData(feeErc20Token.address);
exchange = await ExchangeContract.deployFrom0xArtifactAsync( exchange = await ExchangeContract.deployFrom0xArtifactAsync(
exchangeArtifacts.Exchange, exchangeArtifacts.Exchange,
provider, provider,
@ -109,9 +108,10 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
exchange.address, exchange.address,
); );
erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address); feeAssetData = await devUtils.encodeERC20AssetData.callAsync(feeErc20Token.address);
erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20Token2.address); erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20Token.address);
erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId); erc20AssetData2 = await devUtils.encodeERC20AssetData.callAsync(erc20Token2.address);
erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, tokenId);
const defaultOrderParams = { const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS, ...constants.STATIC_ORDER_PARAMS,
makerAddress, makerAddress,
@ -162,7 +162,7 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
expect(transferableAmount).to.bignumber.equal(allowance); expect(transferableAmount).to.bignumber.equal(allowance);
}); });
it('should return the correct transferable amount for multiAssetData', async () => { it('should return the correct transferable amount for multiAssetData', async () => {
const multiAssetData = assetDataUtils.encodeMultiAssetData( const multiAssetData = await devUtils.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)], [new BigNumber(1), new BigNumber(1)],
[erc20AssetData, erc20AssetData2], [erc20AssetData, erc20AssetData2],
); );
@ -227,7 +227,7 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT); expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
}); });
it('should return a fillableTakerAssetAmount of 0 when balances/allowances of one asset within a multiAssetData are insufficient', async () => { it('should return a fillableTakerAssetAmount of 0 when balances/allowances of one asset within a multiAssetData are insufficient', async () => {
const multiAssetData = assetDataUtils.encodeMultiAssetData( const multiAssetData = await devUtils.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)], [new BigNumber(1), new BigNumber(1)],
[erc20AssetData, erc20AssetData2], [erc20AssetData, erc20AssetData2],
); );
@ -285,7 +285,7 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
); );
}); });
it('should return the correct fillableTakerAssetAmount when balances/allowances of one asset within a multiAssetData are partially sufficient', async () => { it('should return the correct fillableTakerAssetAmount when balances/allowances of one asset within a multiAssetData are partially sufficient', async () => {
const multiAssetData = assetDataUtils.encodeMultiAssetData( const multiAssetData = await devUtils.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)], [new BigNumber(1), new BigNumber(1)],
[erc20AssetData, erc20AssetData2], [erc20AssetData, erc20AssetData2],
); );

View File

@ -137,7 +137,7 @@ export class AssetBuyer {
assert.isValidPercentage('feePercentage', feePercentage); assert.isValidPercentage('feePercentage', feePercentage);
assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh); assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh);
assert.isNumber('slippagePercentage', slippagePercentage); assert.isNumber('slippagePercentage', slippagePercentage);
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow(); const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
const isMakerAssetZrxToken = assetData === zrxTokenAssetData; const isMakerAssetZrxToken = assetData === zrxTokenAssetData;
// get the relevant orders for the makerAsset and fees // get the relevant orders for the makerAsset and fees
// if the requested assetData is ZRX, don't get the fee info // if the requested assetData is ZRX, don't get the fee info
@ -177,7 +177,7 @@ export class AssetBuyer {
): Promise<BuyQuote> { ): Promise<BuyQuote> {
assert.isETHAddressHex('tokenAddress', tokenAddress); assert.isETHAddressHex('tokenAddress', tokenAddress);
assert.isBigNumber('assetBuyAmount', assetBuyAmount); assert.isBigNumber('assetBuyAmount', assetBuyAmount);
const assetData = assetDataUtils.encodeERC20AssetData(tokenAddress); const assetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(tokenAddress);
const buyQuote = this.getBuyQuoteAsync(assetData, assetBuyAmount, options); const buyQuote = this.getBuyQuoteAsync(assetData, assetBuyAmount, options);
return buyQuote; return buyQuote;
} }
@ -200,7 +200,7 @@ export class AssetBuyer {
assert.isBoolean('options.shouldForceOrderRefresh', shouldForceOrderRefresh); assert.isBoolean('options.shouldForceOrderRefresh', shouldForceOrderRefresh);
const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData); const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData);
const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow(); const etherTokenAssetData = await this._getEtherTokenAssetDataOrThrowAsync();
if (!assetPairs.includes(etherTokenAssetData)) { if (!assetPairs.includes(etherTokenAssetData)) {
return { return {
tokensAvailableInBaseUnits: new BigNumber(0), tokensAvailableInBaseUnits: new BigNumber(0),
@ -298,7 +298,7 @@ export class AssetBuyer {
* @return An array of asset data strings that can be purchased using wETH. * @return An array of asset data strings that can be purchased using wETH.
*/ */
public async getAvailableAssetDatasAsync(): Promise<string[]> { public async getAvailableAssetDatasAsync(): Promise<string[]> {
const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow(); const etherTokenAssetData = await this._getEtherTokenAssetDataOrThrowAsync();
return this.orderProvider.getAvailableMakerAssetDatasAsync(etherTokenAssetData); return this.orderProvider.getAvailableMakerAssetDatasAsync(etherTokenAssetData);
} }
/** /**
@ -325,8 +325,8 @@ export class AssetBuyer {
const result = ordersEntryIfExists.ordersAndFillableAmounts; const result = ordersEntryIfExists.ordersAndFillableAmounts;
return result; return result;
} }
const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow(); const etherTokenAssetData = await this._getEtherTokenAssetDataOrThrowAsync();
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow(); const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
// construct orderProvider request // construct orderProvider request
const orderProviderRequest = { const orderProviderRequest = {
makerAssetData: assetData, makerAssetData: assetData,
@ -359,14 +359,18 @@ export class AssetBuyer {
* Get the assetData that represents the WETH token. * Get the assetData that represents the WETH token.
* Will throw if WETH does not exist for the current chain. * Will throw if WETH does not exist for the current chain.
*/ */
private _getEtherTokenAssetDataOrThrow(): string { private async _getEtherTokenAssetDataOrThrowAsync(): Promise<string> {
return assetDataUtils.encodeERC20AssetData(this._contractWrappers.contractAddresses.etherToken); return this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(
this._contractWrappers.contractAddresses.etherToken,
);
} }
/** /**
* Get the assetData that represents the ZRX token. * Get the assetData that represents the ZRX token.
* Will throw if ZRX does not exist for the current chain. * Will throw if ZRX does not exist for the current chain.
*/ */
private _getZrxTokenAssetDataOrThrow(): string { private async _getZrxTokenAssetDataOrThrowAsync(): Promise<string> {
return assetDataUtils.encodeERC20AssetData(this._contractWrappers.contractAddresses.zrxToken); return this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(
this._contractWrappers.contractAddresses.zrxToken,
);
} }
} }

View File

@ -1,5 +1,4 @@
import { ContractError, ContractWrappers, ForwarderError } from '@0x/contract-wrappers'; import { ContractError, ContractWrappers, ForwarderError } from '@0x/contract-wrappers';
import { assetDataUtils } from '@0x/order-utils';
import { MarketOperation } from '@0x/types'; import { MarketOperation } from '@0x/types';
import { AbiEncoder, providerUtils } from '@0x/utils'; import { AbiEncoder, providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from '@0x/web3-wrapper'; import { SupportedProvider, ZeroExProvider } from '@0x/web3-wrapper';
@ -50,7 +49,7 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase<Forward
quote: SwapQuote, quote: SwapQuote,
opts: Partial<ForwarderSwapQuoteGetOutputOpts>, opts: Partial<ForwarderSwapQuoteGetOutputOpts>,
): Promise<CalldataInfo> { ): Promise<CalldataInfo> {
assert.isValidForwarderSwapQuote('quote', quote, this._getEtherTokenAssetDataOrThrow()); assert.isValidForwarderSwapQuote('quote', quote, await this._getEtherTokenAssetDataOrThrowAsync());
const { toAddress, methodAbi, ethAmount, params } = await this.getSmartContractParamsOrThrowAsync(quote, opts); const { toAddress, methodAbi, ethAmount, params } = await this.getSmartContractParamsOrThrowAsync(quote, opts);
@ -82,7 +81,7 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase<Forward
quote: SwapQuote, quote: SwapQuote,
opts: Partial<ForwarderSwapQuoteGetOutputOpts>, opts: Partial<ForwarderSwapQuoteGetOutputOpts>,
): Promise<SmartContractParamsInfo<ForwarderSmartContractParams>> { ): Promise<SmartContractParamsInfo<ForwarderSmartContractParams>> {
assert.isValidForwarderSwapQuote('quote', quote, this._getEtherTokenAssetDataOrThrow()); assert.isValidForwarderSwapQuote('quote', quote, await this._getEtherTokenAssetDataOrThrowAsync());
const { ethAmount, feeRecipient, feePercentage: unFormattedFeePercentage } = _.merge( const { ethAmount, feeRecipient, feePercentage: unFormattedFeePercentage } = _.merge(
{}, {},
@ -160,7 +159,7 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase<Forward
quote: SwapQuote, quote: SwapQuote,
opts: Partial<ForwarderSwapQuoteExecutionOpts>, opts: Partial<ForwarderSwapQuoteExecutionOpts>,
): Promise<string> { ): Promise<string> {
assert.isValidForwarderSwapQuote('quote', quote, this._getEtherTokenAssetDataOrThrow()); assert.isValidForwarderSwapQuote('quote', quote, await this._getEtherTokenAssetDataOrThrowAsync());
const { ethAmount, takerAddress, gasLimit, gasPrice, feeRecipient, feePercentage } = _.merge( const { ethAmount, takerAddress, gasLimit, gasPrice, feeRecipient, feePercentage } = _.merge(
{}, {},
@ -236,7 +235,9 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase<Forward
} }
} }
private _getEtherTokenAssetDataOrThrow(): string { private async _getEtherTokenAssetDataOrThrowAsync(): Promise<string> {
return assetDataUtils.encodeERC20AssetData(this._contractWrappers.contractAddresses.etherToken); return this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(
this._contractWrappers.contractAddresses.etherToken,
);
} }
} }

View File

@ -216,8 +216,8 @@ export class SwapQuoter {
assert.isETHAddressHex('makerTokenAddress', makerTokenAddress); assert.isETHAddressHex('makerTokenAddress', makerTokenAddress);
assert.isETHAddressHex('takerTokenAddress', takerTokenAddress); assert.isETHAddressHex('takerTokenAddress', takerTokenAddress);
assert.isBigNumber('makerAssetBuyAmount', makerAssetBuyAmount); assert.isBigNumber('makerAssetBuyAmount', makerAssetBuyAmount);
const makerAssetData = assetDataUtils.encodeERC20AssetData(makerTokenAddress); const makerAssetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress);
const takerAssetData = assetDataUtils.encodeERC20AssetData(takerTokenAddress); const takerAssetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress);
const swapQuote = this.getMarketBuySwapQuoteForAssetDataAsync( const swapQuote = this.getMarketBuySwapQuoteForAssetDataAsync(
makerAssetData, makerAssetData,
takerAssetData, takerAssetData,
@ -246,8 +246,8 @@ export class SwapQuoter {
assert.isETHAddressHex('makerTokenAddress', makerTokenAddress); assert.isETHAddressHex('makerTokenAddress', makerTokenAddress);
assert.isETHAddressHex('takerTokenAddress', takerTokenAddress); assert.isETHAddressHex('takerTokenAddress', takerTokenAddress);
assert.isBigNumber('takerAssetSellAmount', takerAssetSellAmount); assert.isBigNumber('takerAssetSellAmount', takerAssetSellAmount);
const makerAssetData = assetDataUtils.encodeERC20AssetData(makerTokenAddress); const makerAssetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress);
const takerAssetData = assetDataUtils.encodeERC20AssetData(takerTokenAddress); const takerAssetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress);
const swapQuote = this.getMarketSellSwapQuoteForAssetDataAsync( const swapQuote = this.getMarketSellSwapQuoteForAssetDataAsync(
makerAssetData, makerAssetData,
takerAssetData, takerAssetData,
@ -346,7 +346,7 @@ export class SwapQuoter {
assert.isString('takerAssetData', takerAssetData); assert.isString('takerAssetData', takerAssetData);
assetDataUtils.decodeAssetDataOrThrow(makerAssetData); assetDataUtils.decodeAssetDataOrThrow(makerAssetData);
assetDataUtils.decodeAssetDataOrThrow(takerAssetData); assetDataUtils.decodeAssetDataOrThrow(takerAssetData);
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow(); const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
// get orders // get orders
const response = await this.orderbook.getOrdersAsync(makerAssetData, takerAssetData); const response = await this.orderbook.getOrdersAsync(makerAssetData, takerAssetData);
const adaptedResponse = { orders: response.map(o => ({ ...o.order, ...o.metaData })) }; const adaptedResponse = { orders: response.map(o => ({ ...o.order, ...o.metaData })) };
@ -396,8 +396,10 @@ export class SwapQuoter {
* Get the assetData that represents the ZRX token. * Get the assetData that represents the ZRX token.
* Will throw if ZRX does not exist for the current chain. * Will throw if ZRX does not exist for the current chain.
*/ */
private _getZrxTokenAssetDataOrThrow(): string { private async _getZrxTokenAssetDataOrThrowAsync(): Promise<string> {
return assetDataUtils.encodeERC20AssetData(this._contractWrappers.contractAddresses.zrxToken); return this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(
this._contractWrappers.contractAddresses.zrxToken,
);
} }
/** /**
@ -418,7 +420,7 @@ export class SwapQuoter {
assert.isString('makerAssetData', makerAssetData); assert.isString('makerAssetData', makerAssetData);
assert.isString('takerAssetData', takerAssetData); assert.isString('takerAssetData', takerAssetData);
assert.isNumber('slippagePercentage', slippagePercentage); assert.isNumber('slippagePercentage', slippagePercentage);
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow(); const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
const isMakerAssetZrxToken = makerAssetData === zrxTokenAssetData; const isMakerAssetZrxToken = makerAssetData === zrxTokenAssetData;
// get the relevant orders for the makerAsset // get the relevant orders for the makerAsset
const ordersAndFillableAmounts = await this.getOrdersAndFillableAmountsAsync(makerAssetData, takerAssetData); const ordersAndFillableAmounts = await this.getOrdersAndFillableAmountsAsync(makerAssetData, takerAssetData);

View File

@ -1,5 +1,4 @@
import { ContractWrappers } from '@0x/contract-wrappers'; import { ContractWrappers } from '@0x/contract-wrappers';
import { assetDataUtils } from '@0x/order-utils';
import { MarketOperation, SignedOrder } from '@0x/types'; import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import { SupportedProvider, Web3Wrapper } from '@0x/web3-wrapper'; import { SupportedProvider, Web3Wrapper } from '@0x/web3-wrapper';
@ -85,7 +84,9 @@ export const swapQuoteConsumerUtils = {
provider: Provider, provider: Provider,
opts: Partial<GetExtensionContractTypeOpts>, opts: Partial<GetExtensionContractTypeOpts>,
): Promise<ExtensionContractType> { ): Promise<ExtensionContractType> {
const wethAssetData = assetDataUtils.encodeERC20AssetData(contractWrappers.contractAddresses.etherToken); const wethAssetData = await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
contractWrappers.contractAddresses.etherToken,
);
if (swapQuoteConsumerUtils.isValidForwarderSwapQuote(quote, wethAssetData)) { if (swapQuoteConsumerUtils.isValidForwarderSwapQuote(quote, wethAssetData)) {
if (opts.takerAddress !== undefined) { if (opts.takerAddress !== undefined) {
assert.isETHAddressHex('takerAddress', opts.takerAddress); assert.isETHAddressHex('takerAddress', opts.takerAddress);

View File

@ -1,7 +1,6 @@
import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers'; import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers';
import { constants as devConstants, OrderFactory } from '@0x/contracts-test-utils'; import { constants as devConstants, OrderFactory } from '@0x/contracts-test-utils';
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils'; import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { MarketOperation, SignedOrder } from '@0x/types'; import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -67,9 +66,9 @@ describe('ExchangeSwapQuoteConsumer', () => {
[coinbaseAddress, takerAddress, makerAddress, feeRecipient] = userAddresses; [coinbaseAddress, takerAddress, makerAddress, feeRecipient] = userAddresses;
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
[makerAssetData, takerAssetData, wethAssetData] = [ [makerAssetData, takerAssetData, wethAssetData] = [
assetDataUtils.encodeERC20AssetData(makerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress),
assetDataUtils.encodeERC20AssetData(takerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress),
assetDataUtils.encodeERC20AssetData(contractAddresses.etherToken), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(contractAddresses.etherToken),
]; ];
erc20TokenContract = new ERC20TokenContract(makerTokenAddress, provider); erc20TokenContract = new ERC20TokenContract(makerTokenAddress, provider);
@ -80,8 +79,12 @@ describe('ExchangeSwapQuoteConsumer', () => {
takerAddress, takerAddress,
makerAssetData, makerAssetData,
takerAssetData, takerAssetData,
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(contractAddresses.zrxToken), makerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(contractAddresses.zrxToken), contractAddresses.zrxToken,
),
takerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
contractAddresses.zrxToken,
),
exchangeAddress: contractAddresses.exchange, exchangeAddress: contractAddresses.exchange,
chainId, chainId,
}; };

View File

@ -1,6 +1,5 @@
import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers'; import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers';
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils'; import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { MarketOperation, SignedOrder } from '@0x/types'; import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -67,9 +66,9 @@ describe('ForwarderSwapQuoteConsumer', () => {
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
erc20Token = new ERC20TokenContract(makerTokenAddress, provider); erc20Token = new ERC20TokenContract(makerTokenAddress, provider);
[makerAssetData, takerAssetData, wethAssetData] = [ [makerAssetData, takerAssetData, wethAssetData] = [
assetDataUtils.encodeERC20AssetData(makerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress),
assetDataUtils.encodeERC20AssetData(takerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress),
assetDataUtils.encodeERC20AssetData(contractAddresses.etherToken), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(contractAddresses.etherToken),
]; ];
}); });
after(async () => { after(async () => {

View File

@ -1,6 +1,5 @@
import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers'; import { ContractAddresses, ContractWrappers, ERC20TokenContract } from '@0x/contract-wrappers';
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils'; import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { MarketOperation, SignedOrder } from '@0x/types'; import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -61,9 +60,9 @@ describe('SwapQuoteConsumer', () => {
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
erc20Token = new ERC20TokenContract(makerTokenAddress, provider); erc20Token = new ERC20TokenContract(makerTokenAddress, provider);
[makerAssetData, takerAssetData, wethAssetData] = [ [makerAssetData, takerAssetData, wethAssetData] = [
assetDataUtils.encodeERC20AssetData(makerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress),
assetDataUtils.encodeERC20AssetData(takerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress),
assetDataUtils.encodeERC20AssetData(contractAddresses.etherToken), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(contractAddresses.etherToken),
]; ];
}); });
after(async () => { after(async () => {

View File

@ -1,6 +1,5 @@
import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers'; import { ContractAddresses, ContractWrappers } from '@0x/contract-wrappers';
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils'; import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { MarketOperation, SignedOrder } from '@0x/types'; import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -53,9 +52,9 @@ describe('swapQuoteConsumerUtils', () => {
[takerAddress, makerAddress] = userAddresses; [takerAddress, makerAddress] = userAddresses;
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
[makerAssetData, takerAssetData, wethAssetData] = [ [makerAssetData, takerAssetData, wethAssetData] = [
assetDataUtils.encodeERC20AssetData(makerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress),
assetDataUtils.encodeERC20AssetData(takerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress),
assetDataUtils.encodeERC20AssetData(contractAddresses.etherToken), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(contractAddresses.etherToken),
]; ];
swapQuoteConsumer = new SwapQuoteConsumer(provider, { swapQuoteConsumer = new SwapQuoteConsumer(provider, {

View File

@ -80,9 +80,9 @@ export class BaseContract {
public address: string; public address: string;
public contractName: string; public contractName: string;
public constructorArgs: any[] = []; public constructorArgs: any[] = [];
public _deployedBytecodeIfExists?: Buffer;
private _evmIfExists?: VM; private _evmIfExists?: VM;
private _evmAccountIfExists?: Buffer; private _evmAccountIfExists?: Buffer;
private _deployedBytecodeIfExists?: Buffer;
protected static _formatABIDataItemList( protected static _formatABIDataItemList(
abis: DataItem[], abis: DataItem[],
values: any[], values: any[],

View File

@ -1,36 +1,13 @@
import { assert as sharedAssert } from '@0x/assert'; import { assert as sharedAssert } from '@0x/assert';
// HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here // HACK: We need those two unused imports because they're actually used by sharedAssert which gets injected here
import { Schema } from '@0x/json-schemas'; // tslint:disable-line:no-unused-variable import { Schema } from '@0x/json-schemas'; // tslint:disable-line:no-unused-variable
import { assetDataUtils, signatureUtils } from '@0x/order-utils';
import { Order } from '@0x/types'; // tslint:disable-line:no-unused-variable import { Order } from '@0x/types'; // tslint:disable-line:no-unused-variable
import { BigNumber } from '@0x/utils'; // tslint:disable-line:no-unused-variable import { BigNumber } from '@0x/utils'; // tslint:disable-line:no-unused-variable
import { Web3Wrapper } from '@0x/web3-wrapper'; import { Web3Wrapper } from '@0x/web3-wrapper';
import { SupportedProvider } from 'ethereum-types';
import * as _ from 'lodash'; import * as _ from 'lodash';
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
export const assert = { export const assert = {
...sharedAssert, ...sharedAssert,
async isValidSignatureAsync(
supportedProvider: SupportedProvider,
orderHash: string,
signature: string,
signerAddress: string,
): Promise<void> {
const isValid = await signatureUtils.isValidSignatureAsync(
supportedProvider,
orderHash,
signature,
signerAddress,
);
sharedAssert.assert(isValid, `Expected order with hash '${orderHash}' to have a valid signature`);
},
isValidSubscriptionToken(variableName: string, subscriptionToken: string): void {
const uuidRegex = new RegExp('^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$');
const isValid = uuidRegex.test(subscriptionToken);
sharedAssert.assert(isValid, `Expected ${variableName} to be a valid subscription token`);
},
async isSenderAddressAsync( async isSenderAddressAsync(
variableName: string, variableName: string,
senderAddressHex: string, senderAddressHex: string,
@ -43,53 +20,4 @@ export const assert = {
`Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`, `Specified ${variableName} ${senderAddressHex} isn't available through the supplied web3 provider`,
); );
}, },
ordersCanBeUsedForForwarderContract(orders: Order[], etherTokenAddress: string): void {
sharedAssert.assert(!_.isEmpty(orders), 'Expected at least 1 signed order. Found no orders');
assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'makerAssetData');
assert.allTakerAssetDatasAreErc20Token(orders, etherTokenAddress);
assert.allTakerAddressesAreNull(orders);
},
feeOrdersCanBeUsedForForwarderContract(orders: Order[], zrxTokenAddress: string, etherTokenAddress: string): void {
if (!_.isEmpty(orders)) {
assert.allMakerAssetDatasAreErc20Token(orders, zrxTokenAddress);
assert.allTakerAssetDatasAreErc20Token(orders, etherTokenAddress);
}
},
allTakerAddressesAreNull(orders: Order[]): void {
assert.ordersHaveAtMostOneUniqueValueForProperty(orders, 'takerAddress', NULL_ADDRESS);
},
allMakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void {
assert.ordersHaveAtMostOneUniqueValueForProperty(
orders,
'makerAssetData',
assetDataUtils.encodeERC20AssetData(tokenAddress),
);
},
allTakerAssetDatasAreErc20Token(orders: Order[], tokenAddress: string): void {
assert.ordersHaveAtMostOneUniqueValueForProperty(
orders,
'takerAssetData',
assetDataUtils.encodeERC20AssetData(tokenAddress),
);
},
/*
* Asserts that all the orders have the same value for the provided propertyName
* If the value parameter is provided, this asserts that all orders have the prope
*/
ordersHaveAtMostOneUniqueValueForProperty(orders: Order[], propertyName: string, value?: any): void {
const allValues = _.map(orders, order => _.get(order, propertyName));
sharedAssert.hasAtMostOneUniqueValue(
allValues,
`Expected all orders to have the same ${propertyName} field. Found the following ${propertyName} values: ${JSON.stringify(
allValues,
)}`,
);
if (value !== undefined) {
const firstValue = _.head(allValues);
sharedAssert.assert(
firstValue === value,
`Expected all orders to have a ${propertyName} field with value: ${value}. Found: ${firstValue}`,
);
}
},
}; };

View File

@ -1,6 +1,5 @@
import { constants, OrderFactory } from '@0x/contracts-test-utils'; import { constants, OrderFactory } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils'; import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types'; import { SignedOrder } from '@0x/types';
import { addressUtils, BigNumber } from '@0x/utils'; import { addressUtils, BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -43,36 +42,62 @@ describe('ABI Decoding Calldata', () => {
exchangeAddress, exchangeAddress,
chainId, chainId,
}; };
contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
const config = {
chainId: constants.TESTRPC_CHAIN_ID,
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);
// Create orders to match. // Create orders to match.
// Values are arbitrary, with the exception of maker addresses (generated above). // Values are arbitrary, with the exception of maker addresses (generated above).
orderLeft = { orderLeft = {
makerAddress: makerAddressLeft, makerAddress: makerAddressLeft,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
makerAssetAmount: new BigNumber(10), makerAssetAmount: new BigNumber(10),
takerAddress: '0x0000000000000000000000000000000000000000', takerAddress: '0x0000000000000000000000000000000000000000',
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
takerAssetAmount: new BigNumber(1), takerAssetAmount: new BigNumber(1),
feeRecipientAddress, feeRecipientAddress,
makerFee: new BigNumber(0), makerFee: new BigNumber(0),
takerFee: new BigNumber(0), takerFee: new BigNumber(0),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), defaultERC20MakerAssetAddress,
),
takerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
senderAddress: '0x0000000000000000000000000000000000000000', senderAddress: '0x0000000000000000000000000000000000000000',
expirationTimeSeconds: new BigNumber(1549498915), expirationTimeSeconds: new BigNumber(1549498915),
salt: new BigNumber(217), salt: new BigNumber(217),
}; };
orderRight = { orderRight = {
makerAddress: makerAddressRight, makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
makerAssetAmount: new BigNumber(1), makerAssetAmount: new BigNumber(1),
takerAddress: '0x0000000000000000000000000000000000000000', takerAddress: '0x0000000000000000000000000000000000000000',
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), takerAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
takerAssetAmount: new BigNumber(8), takerAssetAmount: new BigNumber(8),
feeRecipientAddress, feeRecipientAddress,
makerFee: new BigNumber(0), makerFee: new BigNumber(0),
takerFee: new BigNumber(0), takerFee: new BigNumber(0),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), makerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress), defaultERC20MakerAssetAddress,
),
takerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
senderAddress: '0x0000000000000000000000000000000000000000', senderAddress: '0x0000000000000000000000000000000000000000',
expirationTimeSeconds: new BigNumber(1549498915), expirationTimeSeconds: new BigNumber(1549498915),
salt: new BigNumber(50010), salt: new BigNumber(50010),
@ -82,14 +107,6 @@ describe('ABI Decoding Calldata', () => {
const orderFactoryRight = new OrderFactory(privateKeyRight, orderRight); const orderFactoryRight = new OrderFactory(privateKeyRight, orderRight);
signedOrderRight = await orderFactoryRight.newSignedOrderAsync(domainInfo); signedOrderRight = await orderFactoryRight.newSignedOrderAsync(domainInfo);
// Encode match orders transaction // Encode match orders transaction
contractAddresses = await migrateOnceAsync();
await blockchainLifecycle.startAsync();
const config = {
chainId: constants.TESTRPC_CHAIN_ID,
contractAddresses,
blockPollingIntervalMs: 10,
};
contractWrappers = new ContractWrappers(provider, config);
matchOrdersTxData = getAbiEncodedTransactionData( matchOrdersTxData = getAbiEncodedTransactionData(
contractWrappers.exchange, contractWrappers.exchange,
'matchOrders', 'matchOrders',

View File

@ -1,7 +1,6 @@
import { constants, OrderFactory } from '@0x/contracts-test-utils'; import { constants, OrderFactory } from '@0x/contracts-test-utils';
import { defaultOrmConfig, getAppAsync } from '@0x/coordinator-server'; import { defaultOrmConfig, getAppAsync } from '@0x/coordinator-server';
import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils'; import { BlockchainLifecycle, tokenUtils } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types'; import { SignedOrder } from '@0x/types';
import { BigNumber, fetchAsync, logUtils, providerUtils } from '@0x/utils'; import { BigNumber, fetchAsync, logUtils, providerUtils } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
@ -86,9 +85,9 @@ describe.skip('CoordinatorWrapper', () => {
[makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses(); [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
feeTokenAddress = contractAddresses.zrxToken; feeTokenAddress = contractAddresses.zrxToken;
[makerAssetData, takerAssetData, feeAssetData] = [ [makerAssetData, takerAssetData, feeAssetData] = [
assetDataUtils.encodeERC20AssetData(makerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress),
assetDataUtils.encodeERC20AssetData(takerTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress),
assetDataUtils.encodeERC20AssetData(feeTokenAddress), await contractWrappers.devUtils.encodeERC20AssetData.callAsync(feeTokenAddress),
]; ];
// Configure order defaults // Configure order defaults

View File

@ -1,6 +1,6 @@
before('set up mocha', async function(): Promise<void> { before('set up mocha', async function(): Promise<void> {
// HACK: Since the migrations take longer then our global mocha timeout limit // HACK: Since the migrations take longer then our global mocha timeout limit
// we manually increase it for this before hook. // we manually increase it for this before hook.
const mochaTestTimeoutMs = 50000; const mochaTestTimeoutMs = 500000;
this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
}); });

View File

@ -296,7 +296,7 @@ export const assetDataUtils = {
throw new Error( throw new Error(
`Could not decode assetData. Expected length of encoded data to be at least 10. Got ${ `Could not decode assetData. Expected length of encoded data to be at least 10. Got ${
assetData.length assetData.length
} for assetData ${assetData}`, }`,
); );
} }
const assetProxyId = assetData.slice(0, constants.SELECTOR_CHAR_LENGTH_WITH_PREFIX); const assetProxyId = assetData.slice(0, constants.SELECTOR_CHAR_LENGTH_WITH_PREFIX);

View File

@ -1,11 +1,16 @@
import { import {
AssetProxyId,
ERC20AssetData,
ERC721AssetData,
ExchangeContractErrs, ExchangeContractErrs,
MultiAssetData,
ObjectMap, ObjectMap,
OrderRelevantState, OrderRelevantState,
OrderState, OrderState,
OrderStateInvalid, OrderStateInvalid,
OrderStateValid, OrderStateValid,
SignedOrder, SignedOrder,
SingleAssetData,
} from '@0x/types'; } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -309,13 +314,14 @@ export class OrderStateUtils {
): Promise<ObjectMap<BigNumber>> { ): Promise<ObjectMap<BigNumber>> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
let balances: ObjectMap<BigNumber> = { ...initialBalances }; let balances: ObjectMap<BigNumber> = { ...initialBalances };
if (assetDataUtils.isERC20AssetData(decodedAssetData) || assetDataUtils.isERC721AssetData(decodedAssetData)) { if (isERC20AssetData(decodedAssetData) || isERC721AssetData(decodedAssetData)) {
const balance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress); const balance = await this._balanceAndProxyAllowanceFetcher.getBalanceAsync(assetData, traderAddress);
const tokenAddress = decodedAssetData.tokenAddress; // tslint:disable-next-line:no-unnecessary-type-assertion
const tokenAddress = (decodedAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
balances[tokenAddress] = balances[tokenAddress] =
initialBalances[tokenAddress] === undefined ? balance : balances[tokenAddress].plus(balance); initialBalances[tokenAddress] === undefined ? balance : balances[tokenAddress].plus(balance);
} else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { } else if (isMultiAssetData(decodedAssetData)) {
for (const assetDataElement of decodedAssetData.nestedAssetData) { for (const assetDataElement of (decodedAssetData as MultiAssetData).nestedAssetData) {
balances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, balances); balances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, balances);
} }
} }
@ -328,19 +334,30 @@ export class OrderStateUtils {
): Promise<ObjectMap<BigNumber>> { ): Promise<ObjectMap<BigNumber>> {
const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData); const decodedAssetData = assetDataUtils.decodeAssetDataOrThrow(assetData);
let allowances: ObjectMap<BigNumber> = { ...initialAllowances }; let allowances: ObjectMap<BigNumber> = { ...initialAllowances };
if (assetDataUtils.isERC20AssetData(decodedAssetData) || assetDataUtils.isERC721AssetData(decodedAssetData)) { if (isERC20AssetData(decodedAssetData) || isERC721AssetData(decodedAssetData)) {
const allowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync( const allowance = await this._balanceAndProxyAllowanceFetcher.getProxyAllowanceAsync(
assetData, assetData,
traderAddress, traderAddress,
); );
const tokenAddress = decodedAssetData.tokenAddress; // tslint:disable-next-line:no-unnecessary-type-assertion
const tokenAddress = (decodedAssetData as ERC20AssetData | ERC721AssetData).tokenAddress;
allowances[tokenAddress] = allowances[tokenAddress] =
initialAllowances[tokenAddress] === undefined ? allowance : allowances[tokenAddress].plus(allowance); initialAllowances[tokenAddress] === undefined ? allowance : allowances[tokenAddress].plus(allowance);
} else if (assetDataUtils.isMultiAssetData(decodedAssetData)) { } else if (isMultiAssetData(decodedAssetData)) {
for (const assetDataElement of decodedAssetData.nestedAssetData) { for (const assetDataElement of (decodedAssetData as MultiAssetData).nestedAssetData) {
allowances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, allowances); allowances = await this._getAssetBalancesAsync(assetDataElement, traderAddress, allowances);
} }
} }
return allowances; return allowances;
} }
} }
function isERC20AssetData(decodedAssetData: SingleAssetData | MultiAssetData): boolean {
return decodedAssetData.assetProxyId === AssetProxyId.ERC20;
}
function isERC721AssetData(decodedAssetData: SingleAssetData | MultiAssetData): boolean {
return decodedAssetData.assetProxyId === AssetProxyId.ERC721;
}
function isMultiAssetData(decodedAssetData: SingleAssetData | MultiAssetData): boolean {
return decodedAssetData.assetProxyId === AssetProxyId.MultiAsset;
}

View File

@ -1,10 +1,8 @@
import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { AbstractBalanceAndProxyAllowanceFetcher } from '../abstract/abstract_balance_and_proxy_allowance_fetcher'; import { AbstractBalanceAndProxyAllowanceFetcher } from '../abstract/abstract_balance_and_proxy_allowance_fetcher';
import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store'; import { AbstractBalanceAndProxyAllowanceLazyStore } from '../abstract/abstract_balance_and_proxy_allowance_lazy_store';
import { assetDataUtils } from '../asset_data_utils';
/** /**
* Copy on read store for balances/proxyAllowances of tokens/accounts * Copy on read store for balances/proxyAllowances of tokens/accounts
@ -111,25 +109,6 @@ export class BalanceAndProxyAllowanceLazyStore implements AbstractBalanceAndProx
} }
} }
} }
/**
* Clear all ERC721 0x proxy allowances a user has on all items of a specific ERC721 contract
* @param tokenAddress ERc721 token address
* @param userAddress Owner Ethereum address
*/
public deleteAllERC721ProxyAllowance(tokenAddress: string, userAddress: string): void {
for (const assetData in this._proxyAllowance) {
if (this._proxyAllowance.hasOwnProperty(assetData)) {
const decodedAssetData = assetDataUtils.decodeERC721AssetData(assetData);
if (
decodedAssetData.assetProxyId === AssetProxyId.ERC721 &&
decodedAssetData.tokenAddress === tokenAddress &&
this._proxyAllowance[assetData][userAddress] !== undefined
) {
delete this._proxyAllowance[assetData][userAddress];
}
}
}
}
/** /**
* Delete all balances & allowances * Delete all balances & allowances
*/ */

View File

@ -1,11 +1,15 @@
import { DummyERC20TokenContract, ERC20ProxyContract, ERC20TokenContract } from '@0x/abi-gen-wrappers'; import {
DevUtilsContract,
DummyERC20TokenContract,
ERC20ProxyContract,
ERC20TokenContract,
} from '@0x/abi-gen-wrappers';
import * as artifacts from '@0x/contract-artifacts'; import * as artifacts from '@0x/contract-artifacts';
import { BlockchainLifecycle, devConstants } from '@0x/dev-utils'; import { BlockchainLifecycle, devConstants } from '@0x/dev-utils';
import { ExchangeContractErrs } from '@0x/types'; import { ExchangeContractErrs } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import { assetDataUtils } from '../src/asset_data_utils';
import { constants } from '../src/constants'; import { constants } from '../src/constants';
import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator'; import { ExchangeTransferSimulator } from '../src/exchange_transfer_simulator';
import { BalanceAndProxyAllowanceLazyStore } from '../src/store/balance_and_proxy_allowance_lazy_store'; import { BalanceAndProxyAllowanceLazyStore } from '../src/store/balance_and_proxy_allowance_lazy_store';
@ -30,6 +34,7 @@ describe('ExchangeTransferSimulator', async () => {
let exchangeTransferSimulator: ExchangeTransferSimulator; let exchangeTransferSimulator: ExchangeTransferSimulator;
let txHash: string; let txHash: string;
let erc20ProxyAddress: string; let erc20ProxyAddress: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
before(async function(): Promise<void> { before(async function(): Promise<void> {
const mochaTestTimeoutMs = 20000; const mochaTestTimeoutMs = 20000;
this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
@ -67,7 +72,7 @@ describe('ExchangeTransferSimulator', async () => {
totalSupply, totalSupply,
); );
exampleAssetData = assetDataUtils.encodeERC20AssetData(dummyERC20Token.address); exampleAssetData = await devUtils.encodeERC20AssetData.callAsync(dummyERC20Token.address);
}); });
beforeEach(async () => { beforeEach(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();