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",
"changes": [

View File

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

View File

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

View File

@ -1,3 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import {
chaiSetup,
constants,
@ -8,7 +9,6 @@ import {
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId, RevertReason } from '@0x/types';
import { AbiEncoder, BigNumber } from '@0x/utils';
import * as chai from 'chai';
@ -25,6 +25,7 @@ describe('StaticCallProxy', () => {
let fromAddress: string;
let toAddress: string;
let devUtils: DevUtilsContract;
let staticCallProxy: IAssetProxyContract;
let staticCallTarget: TestStaticCallTargetContract;
@ -43,6 +44,7 @@ describe('StaticCallProxy', () => {
txDefaults,
artifacts,
);
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
staticCallProxy = new IAssetProxyContract(
staticCallProxyWithoutTransferFrom.address,
provider,
@ -86,7 +88,7 @@ describe('StaticCallProxy', () => {
it('should revert if assetData lies outside the bounds of calldata', async () => {
const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -114,9 +116,11 @@ describe('StaticCallProxy', () => {
it('should revert if the length of assetData is less than 100 bytes', async () => {
const staticCallData = constants.NULL_BYTES;
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.slice(0, -128);
const assetData = (await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
)).slice(0, -128);
const assetDataByteLen = (assetData.length - 2) / 2;
expect((assetDataByteLen - 4) % 32).to.equal(0);
await expectTransactionFailedWithoutReasonAsync(
@ -126,7 +130,7 @@ describe('StaticCallProxy', () => {
it('should revert if the offset to `staticCallData` points to outside of assetData', async () => {
const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -147,7 +151,7 @@ describe('StaticCallProxy', () => {
it('should revert if the callTarget attempts to write to state', async () => {
const staticCallData = staticCallTarget.updateState.getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -159,7 +163,7 @@ describe('StaticCallProxy', () => {
it('should revert with data provided by the callTarget if the staticcall reverts', async () => {
const staticCallData = staticCallTarget.assertEvenNumber.getABIEncodedTransactionData(new BigNumber(1));
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -173,7 +177,7 @@ describe('StaticCallProxy', () => {
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0));
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -186,7 +190,7 @@ describe('StaticCallProxy', () => {
it('should be successful if a function call with no inputs and no outputs is successful', async () => {
const staticCallData = staticCallTarget.noInputFunction.getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
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 () => {
const staticCallData = '0x0102030405060708';
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);
});
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 trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -214,7 +222,7 @@ describe('StaticCallProxy', () => {
const dynamicInput = '0x0102030405060708';
const staticCallData = staticCallTarget.dynamicInputFunction.getABIEncodedTransactionData(dynamicInput);
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -237,7 +245,7 @@ describe('StaticCallProxy', () => {
const expectedResultHash = ethUtil.bufferToHex(
ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
);
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await devUtils.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
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 {
constants,
@ -7,7 +8,6 @@ import {
LogDecoder,
txDefaults,
} from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -26,6 +26,7 @@ export class ERC1155ProxyWrapper {
private readonly _logDecoder: LogDecoder;
private readonly _dummyTokenWrappers: Erc1155Wrapper[];
private readonly _assetProxyInterface: IAssetProxyContract;
private readonly _devUtils: DevUtilsContract;
private _proxyContract?: ERC1155ProxyContract;
private _proxyIdIfExists?: string;
private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
@ -37,6 +38,7 @@ export class ERC1155ProxyWrapper {
this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
this._dummyTokenWrappers = [];
this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._fungibleTokenIds = [];
@ -95,7 +97,7 @@ export class ERC1155ProxyWrapper {
* @param extraData extra data to append to `transferFrom` transaction. Optional.
* @return abi encoded tx data.
*/
public getTransferFromAbiEncodedTxData(
public async getTransferFromAbiEncodedTxDataAsync(
from: string,
to: string,
contractAddress: string,
@ -105,11 +107,11 @@ export class ERC1155ProxyWrapper {
receiverCallbackData: string,
authorizedSender: string,
assetData_?: string,
): string {
): Promise<string> {
this._validateProxyContractExistsOrThrow();
const assetData =
assetData_ === undefined
? assetDataUtils.encodeERC1155AssetData(
? await this._devUtils.encodeERC1155AssetData.callAsync(
contractAddress,
tokensToTransfer,
valuesToTransfer,
@ -169,7 +171,7 @@ export class ERC1155ProxyWrapper {
this._validateProxyContractExistsOrThrow();
const assetData =
assetData_ === undefined
? assetDataUtils.encodeERC1155AssetData(
? await this._devUtils.encodeERC1155AssetData.callAsync(
contractAddress,
tokensToTransfer,
valuesToTransfer,

View File

@ -1,6 +1,6 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { ZeroExProvider } from 'ethereum-types';
import * as _ from 'lodash';
@ -12,6 +12,7 @@ export class ERC20Wrapper {
private readonly _contractOwnerAddress: string;
private readonly _provider: ZeroExProvider;
private readonly _dummyTokenContracts: DummyERC20TokenContract[];
private readonly _devUtils: DevUtilsContract;
private _proxyContract?: ERC20ProxyContract;
private _proxyIdIfExists?: string;
/**
@ -26,6 +27,7 @@ export class ERC20Wrapper {
this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
}
public async deployDummyTokensAsync(
numberToDeploy: number,
@ -80,24 +82,27 @@ export class ERC20Wrapper {
}
}
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));
return balance;
}
public async setBalanceAsync(userAddress: string, assetData: string, amount: BigNumber): Promise<void> {
const tokenContract = this._getTokenContractFromAssetData(assetData);
await tokenContract.setBalance.awaitTransactionSuccessAsync(userAddress, amount, {
from: this._contractOwnerAddress,
});
const tokenContract = await this._getTokenContractFromAssetDataAsync(assetData);
await tokenContract.setBalance.awaitTransactionSuccessAsync(
userAddress,
amount,
{ from: this._contractOwnerAddress },
{ pollingIntervalMs: constants.AWAIT_TRANSACTION_MINED_MS },
);
}
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 allowance = new BigNumber(await tokenContract.allowance.callAsync(userAddress, proxyAddress));
return allowance;
}
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;
await tokenContract.approve.awaitTransactionSuccessAsync(proxyAddress, amount, { from: userAddress });
}
@ -141,9 +146,8 @@ export class ERC20Wrapper {
const tokenAddresses = _.map(this._dummyTokenContracts, dummyTokenContract => dummyTokenContract.address);
return tokenAddresses;
}
private _getTokenContractFromAssetData(assetData: string): DummyERC20TokenContract {
const erc20ProxyData = assetDataUtils.decodeERC20AssetData(assetData);
const tokenAddress = erc20ProxyData.tokenAddress;
private async _getTokenContractFromAssetDataAsync(assetData: string): Promise<DummyERC20TokenContract> {
const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData.callAsync(assetData); // tslint:disable-line:no-unused-variable
const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
if (tokenContractIfExists === undefined) {
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",
"devDependencies": {
"@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-test-utils": "^3.2.0-beta.0",
"@0x/dev-utils": "^2.4.0-beta.0",
@ -61,6 +66,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
"npm-run-all": "^4.1.2",
@ -72,19 +78,12 @@
},
"dependencies": {
"@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/typescript-typings": "^4.4.0-beta.0",
"@0x/utils": "^4.6.0-beta.0",
"@0x/web3-wrapper": "^6.1.0-beta.0",
"ethereum-types": "^2.2.0-beta.0",
"ethereumjs-util": "^5.1.1",
"lodash": "^4.17.11"
"ethereumjs-util": "^5.1.1"
},
"publishConfig": {
"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",
"changes": [

View File

@ -316,6 +316,29 @@ contract LibAssetData {
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.
/// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded.
/// @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.
/// @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.
function decodeERC20AssetData(bytes memory assetData)
public
@ -515,4 +538,75 @@ contract LibAssetData {
);
// 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": {
"@0x/base-contract": "^5.5.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-erc721": "^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",
"changes": [

View File

@ -76,6 +76,7 @@
"dependencies": {
"@0x/base-contract": "^5.5.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-erc20": "^2.3.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 {
constants,
@ -24,68 +25,8 @@ import {
} from '../../src';
export class FillOrderWrapper {
private readonly _exchange: ExchangeContract;
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.
*/
@ -119,6 +60,65 @@ export class FillOrderWrapper {
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.
* @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.
*/
public constructor(
exchangeContract: ExchangeContract,
private readonly _exchange: ExchangeContract,
private readonly _devUtils: DevUtilsContract,
tokenOwnersByName: TokenOwnersByName,
tokenContractsByName: Partial<TokenContractsByName>,
tokenIds: Partial<TokenIds>,
) {
this._exchange = exchangeContract;
this._blockchainBalanceStore = new BlockchainBalanceStore(tokenOwnersByName, tokenContractsByName, tokenIds);
}
@ -168,7 +168,7 @@ export class FillOrderWrapper {
simulatedFillResults,
simulatedFillEvent,
simulatedFinalBalanceStore,
] = FillOrderWrapper.simulateFillOrder(txReceipt, signedOrder, from, this._blockchainBalanceStore, opts);
] = await this.simulateFillOrderAsync(txReceipt, signedOrder, from, this._blockchainBalanceStore, opts);
// Assert state transition
expect(simulatedFillResults, 'Fill Results').to.be.deep.equal(fillResults);
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 { assetDataUtils } from '@0x/order-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as _ from 'lodash';
@ -12,8 +12,8 @@ export class LocalBalanceStore extends BalanceStore {
* Creates a new balance store based on an existing one.
* @param sourceBalanceStore Existing balance store whose values should be copied.
*/
public static create(sourceBalanceStore?: BalanceStore): LocalBalanceStore {
const localBalanceStore = new LocalBalanceStore();
public static create(devUtils: DevUtilsContract, sourceBalanceStore?: BalanceStore): LocalBalanceStore {
const localBalanceStore = new LocalBalanceStore(devUtils);
if (sourceBalanceStore !== undefined) {
localBalanceStore.cloneFrom(sourceBalanceStore);
}
@ -26,6 +26,7 @@ export class LocalBalanceStore extends BalanceStore {
* be initialized via `create`.
*/
protected constructor(
private readonly _devUtils: DevUtilsContract,
tokenOwnersByName: TokenOwnersByName = {},
tokenContractsByName: Partial<TokenContractsByName> = {},
) {
@ -71,27 +72,33 @@ export class LocalBalanceStore extends BalanceStore {
* @param amount Amount of asset(s) to transfer
* @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) {
return;
}
const assetProxyId = assetDataUtils.decodeAssetProxyId(assetData);
const assetProxyId = await this._devUtils.decodeAssetProxyId.callAsync(assetData);
switch (assetProxyId) {
case AssetProxyId.ERC20: {
const erc20AssetData = assetDataUtils.decodeERC20AssetData(assetData);
const assetAddress = erc20AssetData.tokenAddress;
_.update(this._balances.erc20, [fromAddress, assetAddress], balance => balance.minus(amount));
_.update(this._balances.erc20, [toAddress, assetAddress], balance =>
// tslint:disable-next-line:no-unused-variable
const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData.callAsync(assetData);
_.update(this._balances.erc20, [fromAddress, tokenAddress], balance => balance.minus(amount));
_.update(this._balances.erc20, [toAddress, tokenAddress], balance =>
(balance || constants.ZERO_AMOUNT).plus(amount),
);
break;
}
case AssetProxyId.ERC721: {
const erc721AssetData = assetDataUtils.decodeERC721AssetData(assetData);
const assetAddress = erc721AssetData.tokenAddress;
const tokenId = erc721AssetData.tokenId;
const fromTokens = _.get(this._balances.erc721, [fromAddress, assetAddress], []);
const toTokens = _.get(this._balances.erc721, [toAddress, assetAddress], []);
// tslint:disable-next-line:no-unused-variable
const [proxyId, tokenAddress, tokenId] = await this._devUtils.decodeERC721AssetData.callAsync(
assetData,
);
const fromTokens = _.get(this._balances.erc721, [fromAddress, tokenAddress], []);
const toTokens = _.get(this._balances.erc721, [toAddress, tokenAddress], []);
if (amount.gte(1)) {
const tokenIndex = _.findIndex(fromTokens as BigNumber[], t => t.eq(tokenId));
if (tokenIndex !== -1) {
@ -100,25 +107,29 @@ export class LocalBalanceStore extends BalanceStore {
toTokens.sort();
}
}
_.set(this._balances.erc721, [fromAddress, assetAddress], fromTokens);
_.set(this._balances.erc721, [toAddress, assetAddress], toTokens);
_.set(this._balances.erc721, [fromAddress, tokenAddress], fromTokens);
_.set(this._balances.erc721, [toAddress, tokenAddress], toTokens);
break;
}
case AssetProxyId.ERC1155: {
const erc1155AssetData = assetDataUtils.decodeERC1155AssetData(assetData);
const assetAddress = erc1155AssetData.tokenAddress;
const [
proxyId, // tslint:disable-line:no-unused-variable
tokenAddress,
tokenIds,
tokenValues,
] = await this._devUtils.decodeERC1155AssetData.callAsync(assetData);
const fromBalances = {
// tslint:disable-next-line:no-inferred-empty-object-type
fungible: _.get(this._balances.erc1155, [fromAddress, assetAddress, 'fungible'], {}),
nonFungible: _.get(this._balances.erc1155, [fromAddress, assetAddress, 'nonFungible'], []),
fungible: _.get(this._balances.erc1155, [fromAddress, tokenAddress, 'fungible'], {}),
nonFungible: _.get(this._balances.erc1155, [fromAddress, tokenAddress, 'nonFungible'], []),
};
const toBalances = {
// tslint:disable-next-line:no-inferred-empty-object-type
fungible: _.get(this._balances.erc1155, [toAddress, assetAddress, 'fungible'], {}),
nonFungible: _.get(this._balances.erc1155, [toAddress, assetAddress, 'nonFungible'], []),
fungible: _.get(this._balances.erc1155, [toAddress, tokenAddress, 'fungible'], {}),
nonFungible: _.get(this._balances.erc1155, [toAddress, tokenAddress, 'nonFungible'], []),
};
for (const [i, tokenId] of erc1155AssetData.tokenIds.entries()) {
const tokenValue = erc1155AssetData.tokenValues[i];
for (const [i, tokenId] of tokenIds.entries()) {
const tokenValue = tokenValues[i];
const tokenAmount = amount.times(tokenValue);
if (tokenAmount.gt(0)) {
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, [toAddress, assetAddress], toBalances);
_.set(this._balances.erc1155, [fromAddress, tokenAddress], fromBalances);
_.set(this._balances.erc1155, [toAddress, tokenAddress], toBalances);
break;
}
case AssetProxyId.MultiAsset: {
const multiAssetData = assetDataUtils.decodeMultiAssetData(assetData);
for (const i of _.times(multiAssetData.amounts.length)) {
const nestedAmount = amount.times(multiAssetData.amounts[i]);
const nestedAssetData = multiAssetData.nestedAssetData[i];
this.transferAsset(fromAddress, toAddress, nestedAmount, nestedAssetData);
// tslint:disable-next-line:no-unused-variable
const [proxyId, amounts, nestedAssetData] = await this._devUtils.decodeMultiAssetData.callAsync(
assetData,
);
for (const [i, amt] of amounts.entries()) {
const nestedAmount = amount.times(amt);
await this.transferAssetAsync(fromAddress, toAddress, nestedAmount, nestedAssetData[i]);
}
break;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
// tslint:disable: max-file-line-count
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 {
blockchainTests,
@ -10,7 +11,7 @@ import {
OrderFactory,
TransactionFactory,
} 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 { AbiEncoder, BigNumber } from '@0x/utils';
import { LogWithDecodedArgs, MethodAbi } from 'ethereum-types';
@ -66,6 +67,7 @@ blockchainTests.resets('Exchange transactions', env => {
let takerPrivateKey: Buffer;
let taker2PrivateKey: Buffer;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, env.provider, env.txDefaults);
before(async () => {
chainId = await env.getChainIdAsync();
const accounts = await env.getAccountAddressesAsync();
@ -110,10 +112,10 @@ blockchainTests.resets('Exchange transactions', env => {
...constants.STATIC_ORDER_PARAMS,
makerAddress,
feeRecipientAddress,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerTokenAddress),
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerTokenAddress),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultMakerFeeTokenAddress),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultTakerFeeTokenAddress),
makerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultMakerTokenAddress),
takerAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerTokenAddress),
makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultMakerFeeTokenAddress),
takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(defaultTakerFeeTokenAddress),
exchangeAddress: exchangeInstance.address,
chainId,
};

View File

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

View File

@ -5,6 +5,7 @@ import {
ERC721Wrapper,
MultiAssetProxyContract,
} from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, expect, LogDecoder, orderUtils, signingUtils } from '@0x/contracts-test-utils';
import { BalanceAndProxyAllowanceLazyStore, ExchangeRevertErrors, orderHashUtils } from '@0x/order-utils';
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(
artifacts.Exchange,
@ -156,6 +158,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
await multiAssetProxy.registerAssetProxy.awaitTransactionSuccessAsync(erc1155Proxy.address, { from: ownerAddress });
const orderFactory = new OrderFactoryFromScenario(
devUtils,
userAddresses,
erc20EighteenDecimalTokens.map(token => token.address),
erc20FiveDecimalTokens.map(token => token.address),
@ -457,7 +460,7 @@ export class FillOrderCombinatorialUtils {
fillErrorIfExists?: FillOrderError,
): Promise<void> {
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);
await this._modifyTraderStateAsync(fillScenario, signedOrder, takerAssetFillAmount);
@ -484,8 +487,8 @@ export class FillOrderCombinatorialUtils {
);
}
private _generateSignedOrder(orderScenario: OrderScenario): SignedOrder {
const order = this.orderFactory.generateOrder(orderScenario);
private async _generateSignedOrderAsync(orderScenario: OrderScenario): Promise<SignedOrder> {
const order = await this.orderFactory.generateOrderAsync(orderScenario);
const orderHashBuff = orderHashUtils.getOrderHashBuffer(order);
const signature = signingUtils.signMessage(orderHashBuff, this.makerPrivateKey, SignatureType.EthSign);
const signedOrder = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
import { CoordinatorContract, SignedCoordinatorApproval } from '@0x/contracts-coordinator';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import {
BlockchainBalanceStore,
constants as exchangeConstants,
@ -10,8 +11,16 @@ import {
ExchangeFunctionName,
LocalBalanceStore,
} from '@0x/contracts-exchange';
import { blockchainTests, constants, expect, hexConcat, hexSlice, verifyEvents } from '@0x/contracts-test-utils';
import { assetDataUtils, CoordinatorRevertErrors, orderHashUtils, transactionHashUtils } from '@0x/order-utils';
import {
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 { BigNumber } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -26,6 +35,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
let deployment: DeploymentManager;
let coordinator: CoordinatorContract;
let balanceStore: BlockchainBalanceStore;
let devUtils: DevUtilsContract;
let maker: Maker;
let taker: Actor;
@ -38,6 +48,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
numErc1155TokensToDeploy: 0,
});
coordinator = await deployCoordinatorAsync(deployment, env);
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
const [makerToken, takerToken, makerFeeToken, takerFeeToken] = deployment.tokens.erc20;
@ -53,10 +64,10 @@ blockchainTests.resets('Coordinator integration tests', env => {
orderConfig: {
senderAddress: coordinator.address,
feeRecipientAddress: feeRecipient.address,
makerAssetData: assetDataUtils.encodeERC20AssetData(makerToken.address),
takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken.address),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerFeeToken.address),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(takerFeeToken.address),
makerAssetData: await devUtils.encodeERC20AssetData.callAsync(makerToken.address),
takerAssetData: await devUtils.encodeERC20AssetData.callAsync(takerToken.address),
makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(makerFeeToken.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[],
txReceipt: TransactionReceiptWithDecodedLogs,
msgValue?: BigNumber,
): LocalBalanceStore {
): Promise<LocalBalanceStore> {
let remainingValue = msgValue || constants.ZERO_AMOUNT;
const localBalanceStore = LocalBalanceStore.create(balanceStore);
const localBalanceStore = LocalBalanceStore.create(devUtils, balanceStore);
// Transaction gas cost
localBalanceStore.burnGas(txReceipt.from, DeploymentManager.gasPrice.times(txReceipt.gasUsed));
for (const order of orders) {
// 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
localBalanceStore.transferAsset(maker.address, taker.address, order.makerAssetAmount, order.makerAssetData);
await localBalanceStore.transferAssetAsync(
maker.address,
taker.address,
order.makerAssetAmount,
order.makerAssetData,
);
// Taker -> Fee Recipient
localBalanceStore.transferAsset(
await localBalanceStore.transferAssetAsync(
taker.address,
feeRecipient.address,
order.takerFee,
order.takerFeeAssetData,
);
// Maker -> Fee Recipient
localBalanceStore.transferAsset(
await localBalanceStore.transferAssetAsync(
maker.address,
feeRecipient.address,
order.makerFee,
@ -116,11 +137,11 @@ blockchainTests.resets('Coordinator integration tests', env => {
);
remainingValue = remainingValue.minus(DeploymentManager.protocolFee);
} else {
localBalanceStore.transferAsset(
await localBalanceStore.transferAssetAsync(
taker.address,
deployment.staking.stakingProxy.address,
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 },
);
const expectedBalances = simulateFills([order], txReceipt, DeploymentManager.protocolFee);
const expectedBalances = await simulateFillsAsync([order], txReceipt, DeploymentManager.protocolFee);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -189,7 +210,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address, value: DeploymentManager.protocolFee },
);
const expectedBalances = simulateFills([order], txReceipt, DeploymentManager.protocolFee);
const expectedBalances = await simulateFillsAsync([order], txReceipt, DeploymentManager.protocolFee);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -204,7 +225,11 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ 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();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -219,7 +244,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address },
);
const expectedBalances = simulateFills([order], txReceipt);
const expectedBalances = await simulateFillsAsync([order], txReceipt);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -234,7 +259,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ 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();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, [expectedFillEvent(order)], ExchangeEvents.Fill);
@ -318,7 +343,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: taker.address, value },
);
const expectedBalances = simulateFills(orders, txReceipt, value);
const expectedBalances = await simulateFillsAsync(orders, txReceipt, value);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill);
@ -334,7 +359,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address, value },
);
const expectedBalances = simulateFills(orders, txReceipt, value);
const expectedBalances = await simulateFillsAsync(orders, txReceipt, value);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill);
@ -350,7 +375,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
{ from: feeRecipient.address, value },
);
const expectedBalances = simulateFills(orders, txReceipt, value);
const expectedBalances = await simulateFillsAsync(orders, txReceipt, value);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
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 { DummyERC721TokenContract } from '@0x/contracts-erc721';
import {
@ -13,9 +14,10 @@ import {
expect,
getLatestBlockTimestampAsync,
getPercentageOfValue,
provider,
toBaseUnitAmount,
} from '@0x/contracts-test-utils';
import { assetDataUtils, ForwarderRevertErrors } from '@0x/order-utils';
import { ForwarderRevertErrors } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import { Actor, actorAddressesByName, FeeRecipient, Maker } from '../actors';
@ -24,6 +26,8 @@ import { DeploymentManager } from '../utils/deployment_manager';
import { deployForwarderAsync } from './deploy_forwarder';
import { ForwarderTestFactory } from './forwarder_test_factory';
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
blockchainTests('Forwarder integration tests', env => {
let deployment: DeploymentManager;
let forwarder: ForwarderContract;
@ -53,8 +57,8 @@ blockchainTests('Forwarder integration tests', env => {
[makerToken, makerFeeToken, anotherErc20Token] = deployment.tokens.erc20;
[erc721Token] = deployment.tokens.erc721;
wethAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.weth.address);
makerAssetData = assetDataUtils.encodeERC20AssetData(makerToken.address);
wethAssetData = await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.weth.address);
makerAssetData = await devUtils.encodeERC20AssetData.callAsync(makerToken.address);
taker = new Actor({ name: 'Taker', deployment });
orderFeeRecipient = new FeeRecipient({
@ -75,7 +79,7 @@ blockchainTests('Forwarder integration tests', env => {
makerAssetData,
takerAssetData: wethAssetData,
takerFee: constants.ZERO_AMOUNT,
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(makerFeeToken.address),
makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(makerFeeToken.address),
takerFeeAssetData: wethAssetData,
},
});
@ -106,6 +110,7 @@ blockchainTests('Forwarder integration tests', env => {
taker,
orderFeeRecipient,
forwarderFeeRecipient,
devUtils,
);
});
@ -166,7 +171,7 @@ blockchainTests('Forwarder integration tests', env => {
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 () => {
const unapprovedAsset = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address);
const unapprovedAsset = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const order = await maker.signOrderAsync({
makerAssetData: unapprovedAsset,
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));
// Verify balances
@ -236,7 +241,7 @@ blockchainTests('Forwarder integration tests', env => {
});
it('should fill orders with different makerAssetData', async () => {
const firstOrder = await maker.signOrderAsync();
const secondOrderMakerAssetData = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address);
const secondOrderMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const secondOrder = await maker.signOrderAsync({
makerAssetData: secondOrderMakerAssetData,
});
@ -245,7 +250,7 @@ blockchainTests('Forwarder integration tests', env => {
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 () => {
const takerFeeAssetData = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address);
const takerFeeAssetData = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const order = await maker.signOrderAsync({
takerFeeAssetData,
takerFee: toBaseUnitAmount(1),
@ -336,7 +341,7 @@ blockchainTests('Forwarder integration tests', env => {
});
it('should buy exactly makerAssetBuyAmount in orders with different makerAssetData', async () => {
const firstOrder = await maker.signOrderAsync();
const secondOrderMakerAssetData = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address);
const secondOrderMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const secondOrder = await maker.signOrderAsync({
makerAssetData: secondOrderMakerAssetData,
});
@ -385,7 +390,7 @@ blockchainTests('Forwarder integration tests', env => {
it('should buy an ERC721 asset from a single order', async () => {
const erc721Order = await maker.signOrderAsync({
makerAssetAmount: new BigNumber(1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, nftId),
makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, nftId),
takerFeeAssetData: wethAssetData,
});
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 () => {
const erc721orderWithWethFee = await maker.signOrderAsync({
makerAssetAmount: new BigNumber(1),
makerAssetData: assetDataUtils.encodeERC721AssetData(erc721Token.address, nftId),
makerAssetData: await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, nftId),
takerFee: toBaseUnitAmount(1),
takerFeeAssetData: wethAssetData,
});
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 () => {
const takerFeeAssetData = assetDataUtils.encodeERC20AssetData(anotherErc20Token.address);
const takerFeeAssetData = await devUtils.encodeERC20AssetData.callAsync(anotherErc20Token.address);
const order = await maker.signOrderAsync({
takerFeeAssetData,
takerFee: toBaseUnitAmount(1),
@ -491,11 +496,21 @@ blockchainTests('Forwarder integration tests', env => {
);
// Compute expected balances
const expectedBalances = LocalBalanceStore.create(balanceStore);
expectedBalances.transferAsset(maker.address, taker.address, makerAssetFillAmount, makerAssetData);
const expectedBalances = LocalBalanceStore.create(devUtils, balanceStore);
await expectedBalances.transferAssetAsync(
maker.address,
taker.address,
makerAssetFillAmount,
makerAssetData,
);
expectedBalances.wrapEth(taker.address, deployment.tokens.weth.address, ethValue);
expectedBalances.transferAsset(taker.address, maker.address, primaryTakerAssetFillAmount, wethAssetData);
expectedBalances.transferAsset(
await expectedBalances.transferAssetAsync(
taker.address,
maker.address,
primaryTakerAssetFillAmount,
wethAssetData,
);
await expectedBalances.transferAssetAsync(
taker.address,
deployment.staking.stakingProxy.address,
DeploymentManager.protocolFee,
@ -537,15 +552,15 @@ blockchainTests('Forwarder integration tests', env => {
);
// Compute expected balances
const expectedBalances = LocalBalanceStore.create(balanceStore);
expectedBalances.transferAsset(maker.address, taker.address, makerAssetFillAmount, makerAssetData);
const expectedBalances = LocalBalanceStore.create(devUtils, balanceStore);
expectedBalances.transferAssetAsync(maker.address, taker.address, makerAssetFillAmount, makerAssetData);
expectedBalances.wrapEth(
taker.address,
deployment.tokens.weth.address,
takerAssetFillAmount.plus(DeploymentManager.protocolFee),
);
expectedBalances.transferAsset(taker.address, maker.address, takerAssetFillAmount, wethAssetData);
expectedBalances.transferAsset(
expectedBalances.transferAssetAsync(taker.address, maker.address, takerAssetFillAmount, wethAssetData);
expectedBalances.transferAssetAsync(
taker.address,
deployment.staking.stakingProxy.address,
DeploymentManager.protocolFee,

View File

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

View File

@ -1,4 +1,5 @@
import { artifacts as assetProxyArtifacts } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { IERC20TokenEvents, IERC20TokenTransferEventArgs } from '@0x/contracts-erc20';
import {
artifacts as exchangeArtifacts,
@ -16,11 +17,12 @@ import {
expect,
getLatestBlockTimestampAsync,
Numberish,
provider,
toBaseUnitAmount,
TransactionHelper,
verifyEvents,
} 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 { BigNumber } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -32,6 +34,7 @@ import { DeploymentManager } from '../utils/deployment_manager';
const { addFillResults, safeGetPartialAmountFloor } = ReferenceFunctions;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
// tslint:disable:no-unnecessary-type-assertion
blockchainTests.resets('Exchange wrappers', env => {
let maker: Maker;
@ -67,10 +70,10 @@ blockchainTests.resets('Exchange wrappers', env => {
name: 'market maker',
deployment,
orderConfig: {
makerAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[0].address),
takerAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[1].address),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address),
makerAssetData: await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.erc20[0].address),
takerAssetData: await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.erc20[1].address),
makerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.erc20[2].address),
takerFeeAssetData: await devUtils.encodeERC20AssetData.callAsync(deployment.tokens.erc20[2].address),
feeRecipientAddress: feeRecipient,
},
});
@ -106,9 +109,9 @@ blockchainTests.resets('Exchange wrappers', env => {
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, {
...assetProxyArtifacts,
@ -118,7 +121,7 @@ blockchainTests.resets('Exchange wrappers', env => {
});
beforeEach(async () => {
localBalances = LocalBalanceStore.create(initialLocalBalances);
localBalances = LocalBalanceStore.create(devUtils, initialLocalBalances);
});
interface SignedOrderWithValidity {
@ -126,9 +129,13 @@ blockchainTests.resets('Exchange wrappers', env => {
isValid: boolean;
}
function simulateFill(signedOrder: SignedOrder, expectedFillResults: FillResults, shouldUseWeth: boolean): void {
async function simulateFillAsync(
signedOrder: SignedOrder,
expectedFillResults: FillResults,
shouldUseWeth: boolean,
): Promise<void> {
// taker -> maker
localBalances.transferAsset(
await localBalances.transferAssetAsync(
taker.address,
maker.address,
expectedFillResults.takerAssetFilledAmount,
@ -136,7 +143,7 @@ blockchainTests.resets('Exchange wrappers', env => {
);
// maker -> taker
localBalances.transferAsset(
await localBalances.transferAssetAsync(
maker.address,
taker.address,
expectedFillResults.makerAssetFilledAmount,
@ -144,7 +151,7 @@ blockchainTests.resets('Exchange wrappers', env => {
);
// maker -> feeRecipient
localBalances.transferAsset(
await localBalances.transferAssetAsync(
maker.address,
feeRecipient,
expectedFillResults.makerFeePaid,
@ -152,7 +159,7 @@ blockchainTests.resets('Exchange wrappers', env => {
);
// taker -> feeRecipient
localBalances.transferAsset(
await localBalances.transferAssetAsync(
taker.address,
feeRecipient,
expectedFillResults.takerFeePaid,
@ -161,7 +168,7 @@ blockchainTests.resets('Exchange wrappers', env => {
// taker -> protocol fees
if (shouldUseWeth) {
localBalances.transferAsset(
await localBalances.transferAssetAsync(
taker.address,
deployment.staking.stakingProxy.address,
expectedFillResults.protocolFeePaid,
@ -332,7 +339,7 @@ blockchainTests.resets('Exchange wrappers', env => {
const shouldPayWethFees = DeploymentManager.protocolFee.gt(value);
// 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.
await assertResultsAsync(receipt, [{ signedOrder, expectedFillResults, shouldPayWethFees }]);
@ -430,7 +437,7 @@ blockchainTests.resets('Exchange wrappers', env => {
}
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees);
await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
}
const [fillResults, receipt] = await txHelper.getResultAndReceiptAsync(
@ -492,7 +499,7 @@ blockchainTests.resets('Exchange wrappers', env => {
}
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees);
await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
}
const [fillResults, receipt] = await txHelper.getResultAndReceiptAsync(
@ -583,7 +590,7 @@ blockchainTests.resets('Exchange wrappers', env => {
}
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees);
await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
} else {
totalFillResults.push(nullFillResults);
}
@ -696,7 +703,7 @@ blockchainTests.resets('Exchange wrappers', env => {
takerFillAmount,
);
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees);
await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
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 () => {
const differentTakerAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address);
const differentTakerAssetData = await devUtils.encodeERC20AssetData.callAsync(
deployment.tokens.erc20[2].address,
);
signedOrders = [
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 () => {
const differentTakerAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address);
const differentTakerAssetData = await devUtils.encodeERC20AssetData.callAsync(
deployment.tokens.erc20[2].address,
);
signedOrders = [
await maker.signOrderAsync(),
@ -890,7 +901,7 @@ blockchainTests.resets('Exchange wrappers', env => {
makerAssetBought,
);
simulateFill(signedOrder, expectedFillResults, shouldPayWethFees);
await simulateFillAsync(signedOrder, expectedFillResults, shouldPayWethFees);
fillTestInfo.push({ signedOrder, expectedFillResults, shouldPayWethFees });
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 () => {
const differentMakerAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address);
const differentMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(
deployment.tokens.erc20[2].address,
);
signedOrders = [
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 () => {
const differentMakerAssetData = assetDataUtils.encodeERC20AssetData(deployment.tokens.erc20[2].address);
const differentMakerAssetData = await devUtils.encodeERC20AssetData.callAsync(
deployment.tokens.erc20[2].address,
);
signedOrders = [
await maker.signOrderAsync(),

View File

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

View File

@ -50,6 +50,7 @@
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@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-gen": "^1.1.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 { DevUtilsContract } from '@0x/contracts-dev-utils';
import {
blockchainTests,
constants,
expect,
expectTransactionFailedAsync,
filterLogsToArguments,
provider,
} from '@0x/contracts-test-utils';
import { assetDataUtils, StakingRevertErrors } from '@0x/order-utils';
import { StakingRevertErrors } from '@0x/order-utils';
import { RevertReason } from '@0x/types';
import { AuthorizableRevertErrors, BigNumber, SafeMathRevertErrors } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
@ -32,6 +34,8 @@ blockchainTests.resets('ZrxVault unit tests', env => {
let zrxAssetData: string;
let zrxProxyAddress: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
before(async () => {
// create accounts
accounts = await env.getAccountAddressesAsync();
@ -44,7 +48,7 @@ blockchainTests.resets('ZrxVault unit tests', env => {
zrxProxyAddress = erc20ProxyContract.address;
// deploy zrx token
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();

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",
"changes": [

View File

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

View File

@ -1,5 +1,6 @@
import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as crypto from 'crypto';
import {
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 { chaiSetup, constants, LogDecoder, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
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 { artifacts, LibAssetDataContract } from '@0x/contracts-dev-utils';
import { InvalidByteOperationError } from '@0x/utils/lib/src/lib_bytes_revert_errors';
chaiSetup.configure();
const expect = chai.expect;
@ -61,6 +62,13 @@ const KNOWN_MULTI_ASSET_ENCODING = {
assetData:
'0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
};
const KNOWN_STATIC_CALL_ENCODING = {
staticCallTargetAddress: '0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f',
staticCallData: '0xed2cfc9c0000000000000000000000000000000000000000000000000000000000000001',
expectedReturnDataHash: '0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6',
assetData:
'0xc339d10a0000000000000000000000006dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f0000000000000000000000000000000000000000000000000000000000000060b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60000000000000000000000000000000000000000000000000000000000000024ed2cfc9c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
};
describe('LibAssetData', () => {
let exchange: ExchangeContract;
@ -215,6 +223,18 @@ describe('LibAssetData', () => {
});
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 () => {
expect(await libAssetData.encodeERC20AssetData.callAsync(KNOWN_ERC20_ENCODING.address)).to.equal(
KNOWN_ERC20_ENCODING.assetData,
@ -286,35 +306,97 @@ describe('LibAssetData', () => {
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', () => {
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(
erc20TokenTotalSupply,
);
});
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);
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
});
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);
});
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);
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should query ERC1155 balances by asset data', async () => {
const assetData = assetDataUtils.encodeERC1155AssetData(
const assetData = await libAssetData.encodeERC1155AssetData.callAsync(
erc1155Token.address,
[erc1155TokenId],
[new BigNumber(1)],
@ -324,7 +406,7 @@ describe('LibAssetData', () => {
});
it('should return 0 if ERC1155 token does not exist', async () => {
const assetData = assetDataUtils.encodeERC1155AssetData(
const assetData = await libAssetData.encodeERC1155AssetData.callAsync(
constants.NULL_ADDRESS,
[erc1155TokenId],
[new BigNumber(1)],
@ -335,11 +417,11 @@ describe('LibAssetData', () => {
});
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)],
[
assetDataUtils.encodeERC20AssetData(erc20Token.address),
assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId),
await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address),
await libAssetData.encodeERC721AssetData.callAsync(erc721Token.address, firstERC721TokenId),
],
);
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 trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await libAssetData.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -370,7 +452,7 @@ describe('LibAssetData', () => {
const staticCallData = staticCallTarget.isOddNumber.getABIEncodedTransactionData(new BigNumber(0));
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await libAssetData.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
expectedResultHash,
@ -386,7 +468,7 @@ describe('LibAssetData', () => {
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
from: tokenOwnerAddress,
});
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
const assetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
expect(
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
).to.bignumber.equal(allowance);
@ -396,7 +478,10 @@ describe('LibAssetData', () => {
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
from: tokenOwnerAddress,
});
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
const assetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect(
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
).to.bignumber.equal(1);
@ -406,7 +491,10 @@ describe('LibAssetData', () => {
await erc721Token.setApprovalForAll.awaitTransactionSuccessAsync(erc721Proxy.address, true, {
from: tokenOwnerAddress,
});
const assetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
const assetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect(
await libAssetData.getAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
@ -416,7 +504,7 @@ describe('LibAssetData', () => {
await erc1155Token.setApprovalForAll.awaitTransactionSuccessAsync(erc1155Proxy.address, true, {
from: tokenOwnerAddress,
});
const assetData = assetDataUtils.encodeERC1155AssetData(
const assetData = await libAssetData.encodeERC1155AssetData.callAsync(
erc1155Token.address,
[erc1155TokenId],
[new BigNumber(1)],
@ -435,11 +523,11 @@ describe('LibAssetData', () => {
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
from: tokenOwnerAddress,
});
const assetData = assetDataUtils.encodeMultiAssetData(
const assetData = await libAssetData.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)],
[
assetDataUtils.encodeERC20AssetData(erc20Token.address),
assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId),
await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address),
await libAssetData.encodeERC721AssetData.callAsync(erc721Token.address, firstERC721TokenId),
],
);
expect(
@ -456,7 +544,7 @@ describe('LibAssetData', () => {
it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
const staticCallData = AssetProxyId.StaticCall;
const assetData = assetDataUtils.encodeStaticCallAssetData(
const assetData = await libAssetData.encodeStaticCallAssetData.callAsync(
staticCallTarget.address,
staticCallData,
constants.KECCAK256_NULL,
@ -468,8 +556,11 @@ describe('LibAssetData', () => {
describe('getBatchBalances', () => {
it('should query balances for a batch of asset data strings', async () => {
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
const erc20AssetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
const erc721AssetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect(
await libAssetData.getBatchBalances.callAsync(tokenOwnerAddress, [erc20AssetData, erc721AssetData]),
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
@ -482,7 +573,7 @@ describe('LibAssetData', () => {
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
from: tokenOwnerAddress,
});
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
const assetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
expect(
await libAssetData.getBalanceAndAssetProxyAllowance.callAsync(tokenOwnerAddress, assetData),
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), allowance]);
@ -494,7 +585,7 @@ describe('LibAssetData', () => {
await erc20Token.approve.awaitTransactionSuccessAsync(erc20Proxy.address, allowance, {
from: tokenOwnerAddress,
});
const assetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
const assetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
expect(
await libAssetData.getBatchBalancesAndAssetProxyAllowances.callAsync(tokenOwnerAddress, [assetData]),
).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [allowance]]);
@ -510,8 +601,11 @@ describe('LibAssetData', () => {
await erc721Token.approve.awaitTransactionSuccessAsync(erc721Proxy.address, firstERC721TokenId, {
from: tokenOwnerAddress,
});
const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, firstERC721TokenId);
const erc20AssetData = await libAssetData.encodeERC20AssetData.callAsync(erc20Token.address);
const erc721AssetData = await libAssetData.encodeERC721AssetData.callAsync(
erc721Token.address,
firstERC721TokenId,
);
expect(
await libAssetData.getBatchAssetProxyAllowances.callAsync(tokenOwnerAddress, [
erc20AssetData,

View File

@ -19,7 +19,7 @@ import {
web3Wrapper,
} from '@0x/contracts-test-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 { BigNumber, providerUtils } from '@0x/utils';
import * as chai from 'chai';
@ -79,7 +79,6 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
[erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
erc721Proxy = await erc721Wrapper.deployProxyAsync();
feeAssetData = assetDataUtils.encodeERC20AssetData(feeErc20Token.address);
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
exchangeArtifacts.Exchange,
provider,
@ -109,9 +108,10 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
exchange.address,
);
erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20Token2.address);
erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, tokenId);
feeAssetData = await devUtils.encodeERC20AssetData.callAsync(feeErc20Token.address);
erc20AssetData = await devUtils.encodeERC20AssetData.callAsync(erc20Token.address);
erc20AssetData2 = await devUtils.encodeERC20AssetData.callAsync(erc20Token2.address);
erc721AssetData = await devUtils.encodeERC721AssetData.callAsync(erc721Token.address, tokenId);
const defaultOrderParams = {
...constants.STATIC_ORDER_PARAMS,
makerAddress,
@ -162,7 +162,7 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
expect(transferableAmount).to.bignumber.equal(allowance);
});
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)],
[erc20AssetData, erc20AssetData2],
);
@ -227,7 +227,7 @@ describe('OrderValidationUtils/OrderTransferSimulatorUtils', () => {
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 () => {
const multiAssetData = assetDataUtils.encodeMultiAssetData(
const multiAssetData = await devUtils.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)],
[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 () => {
const multiAssetData = assetDataUtils.encodeMultiAssetData(
const multiAssetData = await devUtils.encodeMultiAssetData.callAsync(
[new BigNumber(1), new BigNumber(1)],
[erc20AssetData, erc20AssetData2],
);

View File

@ -137,7 +137,7 @@ export class AssetBuyer {
assert.isValidPercentage('feePercentage', feePercentage);
assert.isBoolean('shouldForceOrderRefresh', shouldForceOrderRefresh);
assert.isNumber('slippagePercentage', slippagePercentage);
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
const isMakerAssetZrxToken = assetData === zrxTokenAssetData;
// get the relevant orders for the makerAsset and fees
// if the requested assetData is ZRX, don't get the fee info
@ -177,7 +177,7 @@ export class AssetBuyer {
): Promise<BuyQuote> {
assert.isETHAddressHex('tokenAddress', tokenAddress);
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);
return buyQuote;
}
@ -200,7 +200,7 @@ export class AssetBuyer {
assert.isBoolean('options.shouldForceOrderRefresh', shouldForceOrderRefresh);
const assetPairs = await this.orderProvider.getAvailableMakerAssetDatasAsync(assetData);
const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow();
const etherTokenAssetData = await this._getEtherTokenAssetDataOrThrowAsync();
if (!assetPairs.includes(etherTokenAssetData)) {
return {
tokensAvailableInBaseUnits: new BigNumber(0),
@ -298,7 +298,7 @@ export class AssetBuyer {
* @return An array of asset data strings that can be purchased using wETH.
*/
public async getAvailableAssetDatasAsync(): Promise<string[]> {
const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow();
const etherTokenAssetData = await this._getEtherTokenAssetDataOrThrowAsync();
return this.orderProvider.getAvailableMakerAssetDatasAsync(etherTokenAssetData);
}
/**
@ -325,8 +325,8 @@ export class AssetBuyer {
const result = ordersEntryIfExists.ordersAndFillableAmounts;
return result;
}
const etherTokenAssetData = this._getEtherTokenAssetDataOrThrow();
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
const etherTokenAssetData = await this._getEtherTokenAssetDataOrThrowAsync();
const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
// construct orderProvider request
const orderProviderRequest = {
makerAssetData: assetData,
@ -359,14 +359,18 @@ export class AssetBuyer {
* Get the assetData that represents the WETH token.
* Will throw if WETH does not exist for the current chain.
*/
private _getEtherTokenAssetDataOrThrow(): string {
return assetDataUtils.encodeERC20AssetData(this._contractWrappers.contractAddresses.etherToken);
private async _getEtherTokenAssetDataOrThrowAsync(): Promise<string> {
return this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(
this._contractWrappers.contractAddresses.etherToken,
);
}
/**
* Get the assetData that represents the ZRX token.
* Will throw if ZRX does not exist for the current chain.
*/
private _getZrxTokenAssetDataOrThrow(): string {
return assetDataUtils.encodeERC20AssetData(this._contractWrappers.contractAddresses.zrxToken);
private async _getZrxTokenAssetDataOrThrowAsync(): Promise<string> {
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 { assetDataUtils } from '@0x/order-utils';
import { MarketOperation } from '@0x/types';
import { AbiEncoder, providerUtils } from '@0x/utils';
import { SupportedProvider, ZeroExProvider } from '@0x/web3-wrapper';
@ -50,7 +49,7 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase<Forward
quote: SwapQuote,
opts: Partial<ForwarderSwapQuoteGetOutputOpts>,
): 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);
@ -82,7 +81,7 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase<Forward
quote: SwapQuote,
opts: Partial<ForwarderSwapQuoteGetOutputOpts>,
): Promise<SmartContractParamsInfo<ForwarderSmartContractParams>> {
assert.isValidForwarderSwapQuote('quote', quote, this._getEtherTokenAssetDataOrThrow());
assert.isValidForwarderSwapQuote('quote', quote, await this._getEtherTokenAssetDataOrThrowAsync());
const { ethAmount, feeRecipient, feePercentage: unFormattedFeePercentage } = _.merge(
{},
@ -160,7 +159,7 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase<Forward
quote: SwapQuote,
opts: Partial<ForwarderSwapQuoteExecutionOpts>,
): Promise<string> {
assert.isValidForwarderSwapQuote('quote', quote, this._getEtherTokenAssetDataOrThrow());
assert.isValidForwarderSwapQuote('quote', quote, await this._getEtherTokenAssetDataOrThrowAsync());
const { ethAmount, takerAddress, gasLimit, gasPrice, feeRecipient, feePercentage } = _.merge(
{},
@ -236,7 +235,9 @@ export class ForwarderSwapQuoteConsumer implements SwapQuoteConsumerBase<Forward
}
}
private _getEtherTokenAssetDataOrThrow(): string {
return assetDataUtils.encodeERC20AssetData(this._contractWrappers.contractAddresses.etherToken);
private async _getEtherTokenAssetDataOrThrowAsync(): Promise<string> {
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('takerTokenAddress', takerTokenAddress);
assert.isBigNumber('makerAssetBuyAmount', makerAssetBuyAmount);
const makerAssetData = assetDataUtils.encodeERC20AssetData(makerTokenAddress);
const takerAssetData = assetDataUtils.encodeERC20AssetData(takerTokenAddress);
const makerAssetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress);
const takerAssetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress);
const swapQuote = this.getMarketBuySwapQuoteForAssetDataAsync(
makerAssetData,
takerAssetData,
@ -246,8 +246,8 @@ export class SwapQuoter {
assert.isETHAddressHex('makerTokenAddress', makerTokenAddress);
assert.isETHAddressHex('takerTokenAddress', takerTokenAddress);
assert.isBigNumber('takerAssetSellAmount', takerAssetSellAmount);
const makerAssetData = assetDataUtils.encodeERC20AssetData(makerTokenAddress);
const takerAssetData = assetDataUtils.encodeERC20AssetData(takerTokenAddress);
const makerAssetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(makerTokenAddress);
const takerAssetData = await this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(takerTokenAddress);
const swapQuote = this.getMarketSellSwapQuoteForAssetDataAsync(
makerAssetData,
takerAssetData,
@ -346,7 +346,7 @@ export class SwapQuoter {
assert.isString('takerAssetData', takerAssetData);
assetDataUtils.decodeAssetDataOrThrow(makerAssetData);
assetDataUtils.decodeAssetDataOrThrow(takerAssetData);
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
// get orders
const response = await this.orderbook.getOrdersAsync(makerAssetData, takerAssetData);
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.
* Will throw if ZRX does not exist for the current chain.
*/
private _getZrxTokenAssetDataOrThrow(): string {
return assetDataUtils.encodeERC20AssetData(this._contractWrappers.contractAddresses.zrxToken);
private async _getZrxTokenAssetDataOrThrowAsync(): Promise<string> {
return this._contractWrappers.devUtils.encodeERC20AssetData.callAsync(
this._contractWrappers.contractAddresses.zrxToken,
);
}
/**
@ -418,7 +420,7 @@ export class SwapQuoter {
assert.isString('makerAssetData', makerAssetData);
assert.isString('takerAssetData', takerAssetData);
assert.isNumber('slippagePercentage', slippagePercentage);
const zrxTokenAssetData = this._getZrxTokenAssetDataOrThrow();
const zrxTokenAssetData = await this._getZrxTokenAssetDataOrThrowAsync();
const isMakerAssetZrxToken = makerAssetData === zrxTokenAssetData;
// get the relevant orders for the makerAsset
const ordersAndFillableAmounts = await this.getOrdersAndFillableAmountsAsync(makerAssetData, takerAssetData);

View File

@ -1,5 +1,4 @@
import { ContractWrappers } from '@0x/contract-wrappers';
import { assetDataUtils } from '@0x/order-utils';
import { MarketOperation, SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { SupportedProvider, Web3Wrapper } from '@0x/web3-wrapper';
@ -85,7 +84,9 @@ export const swapQuoteConsumerUtils = {
provider: Provider,
opts: Partial<GetExtensionContractTypeOpts>,
): 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 (opts.takerAddress !== undefined) {
assert.isETHAddressHex('takerAddress', opts.takerAddress);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,36 +1,13 @@
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
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 { BigNumber } from '@0x/utils'; // tslint:disable-line:no-unused-variable
import { Web3Wrapper } from '@0x/web3-wrapper';
import { SupportedProvider } from 'ethereum-types';
import * as _ from 'lodash';
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
export const assert = {
...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(
variableName: string,
senderAddressHex: string,
@ -43,53 +20,4 @@ export const assert = {
`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 { BlockchainLifecycle } from '@0x/dev-utils';
import { assetDataUtils } from '@0x/order-utils';
import { SignedOrder } from '@0x/types';
import { addressUtils, BigNumber } from '@0x/utils';
import * as chai from 'chai';
@ -43,36 +42,62 @@ describe('ABI Decoding Calldata', () => {
exchangeAddress,
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.
// Values are arbitrary, with the exception of maker addresses (generated above).
orderLeft = {
makerAddress: makerAddressLeft,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
makerAssetAmount: new BigNumber(10),
takerAddress: '0x0000000000000000000000000000000000000000',
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
takerAssetAmount: new BigNumber(1),
feeRecipientAddress,
makerFee: new BigNumber(0),
takerFee: new BigNumber(0),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
takerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
senderAddress: '0x0000000000000000000000000000000000000000',
expirationTimeSeconds: new BigNumber(1549498915),
salt: new BigNumber(217),
};
orderRight = {
makerAddress: makerAddressRight,
makerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
makerAssetAmount: new BigNumber(1),
takerAddress: '0x0000000000000000000000000000000000000000',
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
takerAssetAmount: new BigNumber(8),
feeRecipientAddress,
makerFee: new BigNumber(0),
takerFee: new BigNumber(0),
makerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
takerFeeAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
makerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
takerFeeAssetData: await contractWrappers.devUtils.encodeERC20AssetData.callAsync(
defaultERC20MakerAssetAddress,
),
senderAddress: '0x0000000000000000000000000000000000000000',
expirationTimeSeconds: new BigNumber(1549498915),
salt: new BigNumber(50010),
@ -82,14 +107,6 @@ describe('ABI Decoding Calldata', () => {
const orderFactoryRight = new OrderFactory(privateKeyRight, orderRight);
signedOrderRight = await orderFactoryRight.newSignedOrderAsync(domainInfo);
// 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(
contractWrappers.exchange,
'matchOrders',

View File

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

View File

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

View File

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

View File

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

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