Fixed the bug and moved "contracts-tests" to "contracts-integrations"
This commit is contained in:
@@ -102,6 +102,7 @@
|
||||
"@0x/typescript-typings": "^5.0.1",
|
||||
"@0x/utils": "^5.1.1",
|
||||
"ethereum-types": "^3.0.0",
|
||||
"ethereumjs-util": "^6.2.0",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
45
contracts/integrations/test/dev-utils/get_order_hash.ts
Normal file
45
contracts/integrations/test/dev-utils/get_order_hash.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { artifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
||||
import { Order } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
blockchainTests('DevUtils.getOrderHash', env => {
|
||||
let devUtils: DevUtilsContract;
|
||||
|
||||
before(async () => {
|
||||
devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
||||
artifacts.DevUtils,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
constants.NULL_ADDRESS,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the order hash', async () => {
|
||||
const expectedOrderHash = '0x331cb7e07a757bae130702da6646c26531798c92bcfaf671817268fd2c188531';
|
||||
const exchangeAddress = '0x1dc4c1cefef38a777b15aa20260a54e584b16c48';
|
||||
const chainId = 50;
|
||||
const order: Order = {
|
||||
makerAddress: constants.NULL_ADDRESS,
|
||||
takerAddress: constants.NULL_ADDRESS,
|
||||
senderAddress: constants.NULL_ADDRESS,
|
||||
feeRecipientAddress: constants.NULL_ADDRESS,
|
||||
makerAssetData: constants.NULL_ADDRESS,
|
||||
takerAssetData: constants.NULL_ADDRESS,
|
||||
makerFeeAssetData: constants.NULL_ADDRESS,
|
||||
takerFeeAssetData: constants.NULL_ADDRESS,
|
||||
salt: new BigNumber(0),
|
||||
makerFee: new BigNumber(0),
|
||||
takerFee: new BigNumber(0),
|
||||
makerAssetAmount: new BigNumber(0),
|
||||
takerAssetAmount: new BigNumber(0),
|
||||
expirationTimeSeconds: new BigNumber(0),
|
||||
exchangeAddress,
|
||||
chainId,
|
||||
};
|
||||
expect(await devUtils.getOrderHash(order, new BigNumber(chainId), exchangeAddress).callAsync()).to.be.equal(
|
||||
expectedOrderHash,
|
||||
);
|
||||
});
|
||||
});
|
19
contracts/integrations/test/dev-utils/global_hooks.ts
Normal file
19
contracts/integrations/test/dev-utils/global_hooks.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { env, EnvVars } from '@0x/dev-utils';
|
||||
|
||||
import { coverage, profiler, provider } from '@0x/contracts-test-utils';
|
||||
import { providerUtils } from '@0x/utils';
|
||||
|
||||
before('start web3 provider', () => {
|
||||
providerUtils.startProviderEngine(provider);
|
||||
});
|
||||
after('generate coverage report', async () => {
|
||||
if (env.parseBoolean(EnvVars.SolidityCoverage)) {
|
||||
const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
|
||||
await coverageSubprovider.writeCoverageAsync();
|
||||
}
|
||||
if (env.parseBoolean(EnvVars.SolidityProfiler)) {
|
||||
const profilerSubprovider = profiler.getProfilerSubproviderSingleton();
|
||||
await profilerSubprovider.writeProfilerOutputAsync();
|
||||
}
|
||||
provider.stop();
|
||||
});
|
597
contracts/integrations/test/dev-utils/lib_asset_data.ts
Normal file
597
contracts/integrations/test/dev-utils/lib_asset_data.ts
Normal file
@@ -0,0 +1,597 @@
|
||||
import * as crypto from 'crypto';
|
||||
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||
|
||||
import {
|
||||
artifacts as proxyArtifacts,
|
||||
ERC1155ProxyContract,
|
||||
ERC20ProxyContract,
|
||||
ERC721ProxyContract,
|
||||
MultiAssetProxyContract,
|
||||
StaticCallProxyContract,
|
||||
TestStaticCallTargetContract,
|
||||
} from '@0x/contracts-asset-proxy';
|
||||
import {
|
||||
artifacts as erc1155Artifacts,
|
||||
ERC1155MintableContract,
|
||||
ERC1155TransferSingleEventArgs,
|
||||
} from '@0x/contracts-erc1155';
|
||||
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||
import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
|
||||
import { blockchainTests, constants, expect, LogDecoder } from '@0x/contracts-test-utils';
|
||||
import { AssetProxyId } from '@0x/types';
|
||||
import { BigNumber, LibBytesRevertErrors, StringRevertError } from '@0x/utils';
|
||||
import * as ethUtil from 'ethereumjs-util';
|
||||
|
||||
import { artifacts, LibAssetDataContract } from '@0x/contracts-dev-utils';
|
||||
|
||||
const KNOWN_ERC20_ENCODING = {
|
||||
address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
assetData: '0xf47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
};
|
||||
const KNOWN_ERC721_ENCODING = {
|
||||
address: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
tokenId: new BigNumber(1),
|
||||
assetData:
|
||||
'0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
|
||||
};
|
||||
const KNOWN_ERC1155_ENCODING = {
|
||||
tokenAddress: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
||||
tokenIds: [new BigNumber(100), new BigNumber(1001), new BigNumber(10001)],
|
||||
tokenValues: [new BigNumber(200), new BigNumber(2001), new BigNumber(20001)],
|
||||
callbackData:
|
||||
'0x025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001',
|
||||
assetData:
|
||||
'0xa7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
|
||||
};
|
||||
const KNOWN_MULTI_ASSET_ENCODING = {
|
||||
amounts: [new BigNumber(70), new BigNumber(1), new BigNumber(18)],
|
||||
nestedAssetData: [
|
||||
KNOWN_ERC20_ENCODING.assetData,
|
||||
KNOWN_ERC721_ENCODING.assetData,
|
||||
KNOWN_ERC1155_ENCODING.assetData,
|
||||
],
|
||||
assetData:
|
||||
'0x94cfcdd7000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000024f47261b00000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000204a7cb5fb70000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c480000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000002711000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000007d10000000000000000000000000000000000000000000000000000000000004e210000000000000000000000000000000000000000000000000000000000000044025717920000000000000000000000001dc4c1cefef38a777b15aa20260a54e584b16c4800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
};
|
||||
const KNOWN_STATIC_CALL_ENCODING = {
|
||||
staticCallTargetAddress: '0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f',
|
||||
staticCallData: '0xed2cfc9c0000000000000000000000000000000000000000000000000000000000000001',
|
||||
expectedReturnDataHash: '0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6',
|
||||
assetData:
|
||||
'0xc339d10a0000000000000000000000006dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f0000000000000000000000000000000000000000000000000000000000000060b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60000000000000000000000000000000000000000000000000000000000000024ed2cfc9c000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000',
|
||||
};
|
||||
|
||||
// TODO(jalextowle): This file could really be cleaned up by using the DeploymentManager tool.
|
||||
blockchainTests('LibAssetData', env => {
|
||||
let exchange: ExchangeContract;
|
||||
let erc20Proxy: ERC20ProxyContract;
|
||||
let erc721Proxy: ERC721ProxyContract;
|
||||
let erc1155Proxy: ERC1155ProxyContract;
|
||||
let multiAssetProxy: MultiAssetProxyContract;
|
||||
let staticCallProxy: StaticCallProxyContract;
|
||||
let staticCallTarget: TestStaticCallTargetContract;
|
||||
let libAssetData: LibAssetDataContract;
|
||||
|
||||
let tokenOwnerAddress: string;
|
||||
|
||||
let erc20Token: DummyERC20TokenContract;
|
||||
let erc721Token: DummyERC721TokenContract;
|
||||
let erc1155Token: ERC1155MintableContract;
|
||||
|
||||
const erc20TokenTotalSupply = new BigNumber(1);
|
||||
|
||||
const firstERC721TokenId = new BigNumber(1);
|
||||
const numberOfERC721Tokens = 10;
|
||||
|
||||
let erc1155TokenId: BigNumber;
|
||||
|
||||
before(async () => {
|
||||
const chainId = await env.getChainIdAsync();
|
||||
exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
exchangeArtifacts.Exchange,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
{},
|
||||
new BigNumber(chainId),
|
||||
);
|
||||
|
||||
erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.ERC20Proxy,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.ERC721Proxy,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.ERC1155Proxy,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.MultiAssetProxy,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.StaticCallProxy,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
await exchange.registerAssetProxy(erc20Proxy.address).awaitTransactionSuccessAsync();
|
||||
await exchange.registerAssetProxy(erc721Proxy.address).awaitTransactionSuccessAsync();
|
||||
await exchange.registerAssetProxy(erc1155Proxy.address).awaitTransactionSuccessAsync();
|
||||
await exchange.registerAssetProxy(multiAssetProxy.address).awaitTransactionSuccessAsync();
|
||||
await exchange.registerAssetProxy(staticCallProxy.address).awaitTransactionSuccessAsync();
|
||||
|
||||
libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
|
||||
artifacts.LibAssetData,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
exchange.address,
|
||||
);
|
||||
|
||||
staticCallTarget = await TestStaticCallTargetContract.deployFrom0xArtifactAsync(
|
||||
proxyArtifacts.TestStaticCallTarget,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
[tokenOwnerAddress] = await env.getAccountAddressesAsync();
|
||||
|
||||
erc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
erc20Artifacts.DummyERC20Token,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
'Dummy',
|
||||
'DUM',
|
||||
new BigNumber(1),
|
||||
erc20TokenTotalSupply,
|
||||
);
|
||||
|
||||
erc721Token = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
|
||||
erc721Artifacts.DummyERC721Token,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
'Dummy',
|
||||
'DUM',
|
||||
);
|
||||
// mint `numberOfERC721Tokens` tokens
|
||||
const transactionMinedPromises = [];
|
||||
for (let i = 0; i < numberOfERC721Tokens; i++) {
|
||||
transactionMinedPromises.push(
|
||||
erc721Token.mint(tokenOwnerAddress, firstERC721TokenId.plus(i - 1)).awaitTransactionSuccessAsync(),
|
||||
);
|
||||
}
|
||||
await Promise.all(transactionMinedPromises);
|
||||
|
||||
erc1155Token = await ERC1155MintableContract.deployFrom0xArtifactAsync(
|
||||
erc1155Artifacts.ERC1155Mintable,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
const logDecoder = new LogDecoder(env.web3Wrapper, erc1155Artifacts);
|
||||
const transactionReceipt = await logDecoder.getTxWithDecodedLogsAsync(
|
||||
await erc1155Token.create('uri:Dummy', /*isNonFungible:*/ false).sendTransactionAsync(),
|
||||
);
|
||||
|
||||
// tslint:disable-next-line no-unnecessary-type-assertion
|
||||
erc1155TokenId = (transactionReceipt.logs[0] as LogWithDecodedArgs<ERC1155TransferSingleEventArgs>).args.id;
|
||||
await erc1155Token
|
||||
.mintFungible(erc1155TokenId, [tokenOwnerAddress], [new BigNumber(1)])
|
||||
.awaitTransactionSuccessAsync();
|
||||
});
|
||||
|
||||
it('should have a deployed-to address', () => {
|
||||
expect(libAssetData.address.slice(0, 2)).to.equal('0x');
|
||||
});
|
||||
|
||||
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(assetData).callAsync()).to.equal(proxyId);
|
||||
}
|
||||
});
|
||||
it('should encode ERC20 asset data', async () => {
|
||||
expect(await libAssetData.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address).callAsync()).to.equal(
|
||||
KNOWN_ERC20_ENCODING.assetData,
|
||||
);
|
||||
});
|
||||
|
||||
it('should decode ERC20 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC20AssetData(KNOWN_ERC20_ENCODING.assetData).callAsync()).to.deep.equal([
|
||||
AssetProxyId.ERC20,
|
||||
KNOWN_ERC20_ENCODING.address,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode ERC721 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData
|
||||
.encodeERC721AssetData(KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId)
|
||||
.callAsync(),
|
||||
).to.equal(KNOWN_ERC721_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode ERC721 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal(
|
||||
[AssetProxyId.ERC721, KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId],
|
||||
);
|
||||
});
|
||||
|
||||
it('should encode ERC1155 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData
|
||||
.encodeERC1155AssetData(
|
||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||
KNOWN_ERC1155_ENCODING.tokenValues,
|
||||
KNOWN_ERC1155_ENCODING.callbackData,
|
||||
)
|
||||
.callAsync(),
|
||||
).to.equal(KNOWN_ERC1155_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode ERC1155 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync(),
|
||||
).to.deep.equal([
|
||||
AssetProxyId.ERC1155,
|
||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||
KNOWN_ERC1155_ENCODING.tokenValues,
|
||||
KNOWN_ERC1155_ENCODING.callbackData,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode multiasset data', async () => {
|
||||
expect(
|
||||
await libAssetData
|
||||
.encodeMultiAssetData(
|
||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||
)
|
||||
.callAsync(),
|
||||
).to.equal(KNOWN_MULTI_ASSET_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode multiasset data', async () => {
|
||||
expect(
|
||||
await libAssetData.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync(),
|
||||
).to.deep.equal([
|
||||
AssetProxyId.MultiAsset,
|
||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode StaticCall data', async () => {
|
||||
expect(
|
||||
await libAssetData
|
||||
.encodeStaticCallAssetData(
|
||||
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
|
||||
KNOWN_STATIC_CALL_ENCODING.staticCallData,
|
||||
KNOWN_STATIC_CALL_ENCODING.expectedReturnDataHash,
|
||||
)
|
||||
.callAsync(),
|
||||
).to.equal(KNOWN_STATIC_CALL_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode StaticCall data', async () => {
|
||||
expect(
|
||||
await libAssetData.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(),
|
||||
).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(data).callAsync();
|
||||
}
|
||||
return;
|
||||
});
|
||||
|
||||
it('should revert for invalid assetProxyId', async () => {
|
||||
const badAssetData = `0x${crypto.randomBytes(4).toString('hex')}${constants.NULL_ADDRESS}`;
|
||||
await expect(libAssetData.revertIfInvalidAssetData(badAssetData).callAsync()).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(badData).callAsync()).to.eventually.be.rejectedWith(
|
||||
LibBytesRevertErrors.InvalidByteOperationError,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBalance', () => {
|
||||
it('should query ERC20 balance by asset data', async () => {
|
||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync()).to.bignumber.equal(
|
||||
erc20TokenTotalSupply,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC20 token does not exist', async () => {
|
||||
const assetData = await libAssetData.encodeERC20AssetData(constants.NULL_ADDRESS).callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query ERC721 balance by asset data', async () => {
|
||||
const assetData = await libAssetData
|
||||
.encodeERC721AssetData(erc721Token.address, firstERC721TokenId)
|
||||
.callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync()).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC721 token does not exist', async () => {
|
||||
const assetData = await libAssetData
|
||||
.encodeERC721AssetData(constants.NULL_ADDRESS, firstERC721TokenId)
|
||||
.callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query ERC1155 balances by asset data', async () => {
|
||||
const assetData = await libAssetData
|
||||
.encodeERC1155AssetData(
|
||||
erc1155Token.address,
|
||||
[erc1155TokenId],
|
||||
[new BigNumber(1)],
|
||||
constants.NULL_BYTES,
|
||||
)
|
||||
.callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync()).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC1155 token does not exist', async () => {
|
||||
const assetData = await libAssetData
|
||||
.encodeERC1155AssetData(
|
||||
constants.NULL_ADDRESS,
|
||||
[erc1155TokenId],
|
||||
[new BigNumber(1)],
|
||||
constants.NULL_BYTES,
|
||||
)
|
||||
.callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query multi-asset batch balance by asset data', async () => {
|
||||
const assetData = await libAssetData
|
||||
.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await libAssetData.encodeERC721AssetData(erc721Token.address, firstERC721TokenId).callAsync(),
|
||||
],
|
||||
)
|
||||
.callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync()).to.bignumber.equal(
|
||||
Math.min(erc20TokenTotalSupply.toNumber(), numberOfERC721Tokens),
|
||||
);
|
||||
});
|
||||
|
||||
it('should return a balance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
||||
const fakeAssetData = '0x01020304';
|
||||
const balance = await libAssetData.getBalance(tokenOwnerAddress, fakeAssetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should return a balance of MAX_UINT256 if the the StaticCallProxy assetData contains data for a successful staticcall', async () => {
|
||||
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
|
||||
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
|
||||
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
|
||||
const assetData = await libAssetData
|
||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
||||
.callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
|
||||
it('should return a balance of 0 if the the StaticCallProxy assetData contains data for an unsuccessful staticcall', async () => {
|
||||
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
|
||||
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
|
||||
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
|
||||
const assetData = await libAssetData
|
||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
||||
.callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwnerAddress, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAssetProxyAllowance', () => {
|
||||
it('should query ERC20 allowances by asset data', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve(erc20Proxy.address, allowance).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwnerAddress, assetData).callAsync(),
|
||||
).to.bignumber.equal(allowance);
|
||||
});
|
||||
|
||||
it('should query ERC721 approval by asset data', async () => {
|
||||
await erc721Token.approve(erc721Proxy.address, firstERC721TokenId).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = await libAssetData
|
||||
.encodeERC721AssetData(erc721Token.address, firstERC721TokenId)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwnerAddress, assetData).callAsync(),
|
||||
).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query ERC721 approvalForAll by assetData', async () => {
|
||||
await erc721Token.setApprovalForAll(erc721Proxy.address, true).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = await libAssetData
|
||||
.encodeERC721AssetData(erc721Token.address, firstERC721TokenId)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwnerAddress, assetData).callAsync(),
|
||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
|
||||
it('should query ERC1155 allowances by asset data', async () => {
|
||||
await erc1155Token.setApprovalForAll(erc1155Proxy.address, true).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = await libAssetData
|
||||
.encodeERC1155AssetData(
|
||||
erc1155Token.address,
|
||||
[erc1155TokenId],
|
||||
[new BigNumber(1)],
|
||||
constants.NULL_BYTES,
|
||||
)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwnerAddress, assetData).callAsync(),
|
||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
|
||||
it('should query multi-asset allowances by asset data', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve(erc20Proxy.address, allowance).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
await erc721Token.approve(erc721Proxy.address, firstERC721TokenId).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = await libAssetData
|
||||
.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await libAssetData.encodeERC721AssetData(erc721Token.address, firstERC721TokenId).callAsync(),
|
||||
],
|
||||
)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwnerAddress, assetData).callAsync(),
|
||||
).to.bignumber.equal(1);
|
||||
return;
|
||||
});
|
||||
|
||||
it('should return an allowance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
||||
const fakeAssetData = '0x01020304';
|
||||
const allowance = await libAssetData.getAssetProxyAllowance(tokenOwnerAddress, fakeAssetData).callAsync();
|
||||
expect(allowance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
|
||||
const staticCallData = AssetProxyId.StaticCall;
|
||||
const assetData = await libAssetData
|
||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, constants.KECCAK256_NULL)
|
||||
.callAsync();
|
||||
const allowance = await libAssetData.getAssetProxyAllowance(tokenOwnerAddress, assetData).callAsync();
|
||||
expect(allowance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBatchBalances', () => {
|
||||
it('should query balances for a batch of asset data strings', async () => {
|
||||
const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
const erc721AssetData = await libAssetData
|
||||
.encodeERC721AssetData(erc721Token.address, firstERC721TokenId)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getBatchBalances(tokenOwnerAddress, [erc20AssetData, erc721AssetData]).callAsync(),
|
||||
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), new BigNumber(1)]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBalanceAndAllowance', () => {
|
||||
it('should query balance and allowance together, from asset data', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve(erc20Proxy.address, allowance).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(
|
||||
await libAssetData.getBalanceAndAssetProxyAllowance(tokenOwnerAddress, assetData).callAsync(),
|
||||
).to.deep.equal([new BigNumber(erc20TokenTotalSupply), allowance]);
|
||||
});
|
||||
});
|
||||
describe('getBatchBalancesAndAllowances', () => {
|
||||
it('should query balances and allowances together, from an asset data array', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve(erc20Proxy.address, allowance).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(
|
||||
await libAssetData.getBatchBalancesAndAssetProxyAllowances(tokenOwnerAddress, [assetData]).callAsync(),
|
||||
).to.deep.equal([[new BigNumber(erc20TokenTotalSupply)], [allowance]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBatchAssetProxyAllowances', () => {
|
||||
it('should query allowances for a batch of asset data strings', async () => {
|
||||
const allowance = new BigNumber(1);
|
||||
await erc20Token.approve(erc20Proxy.address, allowance).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
await erc721Token.approve(erc721Proxy.address, firstERC721TokenId).awaitTransactionSuccessAsync({
|
||||
from: tokenOwnerAddress,
|
||||
});
|
||||
const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
const erc721AssetData = await libAssetData
|
||||
.encodeERC721AssetData(erc721Token.address, firstERC721TokenId)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData
|
||||
.getBatchAssetProxyAllowances(tokenOwnerAddress, [erc20AssetData, erc721AssetData])
|
||||
.callAsync(),
|
||||
).to.deep.equal([new BigNumber(1), new BigNumber(1)]);
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable:max-file-line-count
|
140
contracts/integrations/test/dev-utils/lib_transaction_decoder.ts
Normal file
140
contracts/integrations/test/dev-utils/lib_transaction_decoder.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { ExchangeContract } from '@0x/contracts-exchange';
|
||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { artifacts, LibTransactionDecoderContract } from '@0x/contracts-dev-utils';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
|
||||
const order = {
|
||||
makerAddress: '0xe36ea790bc9d7ab70c55260c66d52b1eca985f84',
|
||||
takerAddress: '0x0000000000000000000000000000000000000000',
|
||||
feeRecipientAddress: '0x78dc5d2d739606d31509c31d654056a45185ecb6',
|
||||
senderAddress: '0x6ecbe1db9ef729cbe972c83fb886247691fb6beb',
|
||||
makerAssetAmount: new BigNumber('100000000000000000000'),
|
||||
takerAssetAmount: new BigNumber('200000000000000000000'),
|
||||
makerFee: new BigNumber('1000000000000000000'),
|
||||
takerFee: new BigNumber('1000000000000000000'),
|
||||
expirationTimeSeconds: new BigNumber('1552396423'),
|
||||
salt: new BigNumber('66097384406870180066678463045003379626790660770396923976862707230261946348951'),
|
||||
makerAssetData: '0xf47261b000000000000000000000000034d402f14d58e001d8efbe6585051bf9706aa064',
|
||||
takerAssetData: '0xf47261b000000000000000000000000025b8fe1de9daf8ba351890744ff28cf7dfa8f5e3',
|
||||
makerFeeAssetData: '0xf47261b000000000000000000000000034d402f14d58e001d8efbe6585051bf9706aa064',
|
||||
takerFeeAssetData: '0xf47261b000000000000000000000000025b8fe1de9daf8ba351890744ff28cf7dfa8f5e3',
|
||||
};
|
||||
const takerAssetFillAmount = new BigNumber('100000000000000000000');
|
||||
const signature =
|
||||
'0x1ce8e3c600d933423172b5021158a6be2e818613ff8e762d70ef490c752fd98a626a215f09f169668990414de75a53da221c294a3002f796d004827258b641876e03';
|
||||
|
||||
describe('LibTransactionDecoder', () => {
|
||||
let libTxDecoder: LibTransactionDecoderContract;
|
||||
const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, provider, txDefaults);
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
libTxDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
|
||||
artifacts.LibTransactionDecoder,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
it('should decode an Exchange.batchCancelOrders() transaction', async () => {
|
||||
const input = exchangeInterface.batchCancelOrders([order, order]).getABIEncodedTransactionData();
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
'batchCancelOrders',
|
||||
[order, order],
|
||||
[],
|
||||
[],
|
||||
]);
|
||||
});
|
||||
|
||||
for (const func of ['batchFillOrders', 'batchFillOrdersNoThrow', 'batchFillOrKillOrders']) {
|
||||
const input = (exchangeInterface as any)
|
||||
[func]([order, order], [takerAssetFillAmount, takerAssetFillAmount], [signature, signature])
|
||||
.getABIEncodedTransactionData();
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
func,
|
||||
[order, order],
|
||||
[takerAssetFillAmount, takerAssetFillAmount],
|
||||
[signature, signature],
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
it('should decode an Exchange.cancelOrder() transaction', async () => {
|
||||
const input = exchangeInterface.cancelOrder(order).getABIEncodedTransactionData();
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
'cancelOrder',
|
||||
[order],
|
||||
[],
|
||||
[],
|
||||
]);
|
||||
});
|
||||
|
||||
for (const func of ['fillOrder', 'fillOrKillOrder']) {
|
||||
const input = (exchangeInterface as any)
|
||||
[func](order, takerAssetFillAmount, signature)
|
||||
.getABIEncodedTransactionData();
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
func,
|
||||
[order],
|
||||
[takerAssetFillAmount],
|
||||
[signature],
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
for (const func of [
|
||||
'marketBuyOrdersNoThrow',
|
||||
'marketSellOrdersNoThrow',
|
||||
'marketBuyOrdersFillOrKill',
|
||||
'marketSellOrdersFillOrKill',
|
||||
]) {
|
||||
const input = (exchangeInterface as any)
|
||||
[func]([order, order], takerAssetFillAmount, [signature, signature])
|
||||
.getABIEncodedTransactionData();
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
func,
|
||||
[order, order],
|
||||
[takerAssetFillAmount],
|
||||
[signature, signature],
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
it('should decode an Exchange.matchOrders() transaction', async () => {
|
||||
const complementaryOrder = {
|
||||
...order,
|
||||
makerAddress: order.takerAddress,
|
||||
takerAddress: order.makerAddress,
|
||||
makerAssetData: order.takerAssetData,
|
||||
takerAssetData: order.makerAssetData,
|
||||
makerAssetAmount: order.takerAssetAmount,
|
||||
takerAssetAmount: order.makerAssetAmount,
|
||||
makerFee: order.takerFee,
|
||||
takerFee: order.makerFee,
|
||||
makerFeeAssetData: order.takerFeeAssetData,
|
||||
takerFeeAssetData: order.makerFeeAssetData,
|
||||
};
|
||||
const input = exchangeInterface
|
||||
.matchOrders(order, complementaryOrder, signature, signature)
|
||||
.getABIEncodedTransactionData();
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
'matchOrders',
|
||||
[order, complementaryOrder],
|
||||
[order.takerAssetAmount, complementaryOrder.takerAssetAmount],
|
||||
[signature, signature],
|
||||
]);
|
||||
});
|
||||
});
|
548
contracts/integrations/test/dev-utils/order_validation_utils.ts
Normal file
548
contracts/integrations/test/dev-utils/order_validation_utils.ts
Normal file
@@ -0,0 +1,548 @@
|
||||
import { ERC20ProxyContract } from '@0x/contracts-asset-proxy';
|
||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||
import { ExchangeContract } from '@0x/contracts-exchange';
|
||||
import { blockchainTests, constants, expect, orderHashUtils, OrderStatus } from '@0x/contracts-test-utils';
|
||||
import { assetDataUtils } from '@0x/order-utils';
|
||||
import { OrderTransferResults, SignedOrder } from '@0x/types';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
|
||||
import { Maker } from '../framework/actors/maker';
|
||||
import { DeploymentManager } from '../framework/deployment_manager';
|
||||
|
||||
// TODO(jalextowle): This can be cleaned up by using the actors more.
|
||||
blockchainTests.resets.only('OrderValidationUtils/OrderTransferSimulatorUtils', env => {
|
||||
let takerAddress: string;
|
||||
let owner: string;
|
||||
|
||||
let maker: Maker;
|
||||
let devUtils: DevUtilsContract;
|
||||
let erc20Token: DummyERC20TokenContract;
|
||||
let erc20Token2: DummyERC20TokenContract;
|
||||
let feeErc20Token: DummyERC20TokenContract;
|
||||
let erc20Proxy: ERC20ProxyContract;
|
||||
let exchange: ExchangeContract;
|
||||
|
||||
let erc20AssetData: string;
|
||||
let erc20AssetData2: string;
|
||||
let feeAssetData: string;
|
||||
let erc721AssetData: string;
|
||||
|
||||
let signedOrder: SignedOrder;
|
||||
|
||||
before(async () => {
|
||||
[takerAddress, owner] = await env.getAccountAddressesAsync();
|
||||
|
||||
const deployment = await DeploymentManager.deployAsync(env, {
|
||||
numErc20TokensToDeploy: 3,
|
||||
numErc721TokensToDeploy: 1,
|
||||
owner,
|
||||
});
|
||||
erc20Token = deployment.tokens.erc20[0];
|
||||
erc20Token2 = deployment.tokens.erc20[1];
|
||||
feeErc20Token = deployment.tokens.erc20[2];
|
||||
erc20Proxy = deployment.assetProxies.erc20Proxy;
|
||||
devUtils = deployment.devUtils;
|
||||
exchange = deployment.exchange;
|
||||
|
||||
erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20Token.address);
|
||||
erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20Token2.address);
|
||||
feeAssetData = assetDataUtils.encodeERC20AssetData(feeErc20Token.address);
|
||||
|
||||
maker = new Maker({
|
||||
name: 'Maker',
|
||||
deployment,
|
||||
orderConfig: {
|
||||
makerAssetData: erc20AssetData,
|
||||
takerAssetData: erc20AssetData2,
|
||||
makerFeeAssetData: feeAssetData,
|
||||
takerFeeAssetData: feeAssetData,
|
||||
feeRecipientAddress: constants.NULL_ADDRESS,
|
||||
},
|
||||
});
|
||||
/*
|
||||
await Promise.all(deployment.tokens.erc20.map(async token => maker.configureERC20TokenAsync(token)));
|
||||
*/
|
||||
const [tokenID] = await maker.configureERC721TokenAsync(deployment.tokens.erc721[0]);
|
||||
erc721AssetData = assetDataUtils.encodeERC721AssetData(deployment.tokens.erc721[0].address, tokenID);
|
||||
});
|
||||
|
||||
describe('getTransferableAssetAmount', () => {
|
||||
it('should return the balance when balance < allowance', async () => {
|
||||
const balance = new BigNumber(123);
|
||||
const allowance = new BigNumber(456);
|
||||
await erc20Token.setBalance(maker.address, balance).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, allowance).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const transferableAmount = await devUtils
|
||||
.getTransferableAssetAmount(maker.address, erc20AssetData)
|
||||
.callAsync();
|
||||
expect(transferableAmount).to.bignumber.equal(balance);
|
||||
});
|
||||
it('should return the allowance when allowance < balance', async () => {
|
||||
const balance = new BigNumber(456);
|
||||
const allowance = new BigNumber(123);
|
||||
await erc20Token.setBalance(maker.address, balance).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, allowance).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const transferableAmount = await devUtils
|
||||
.getTransferableAssetAmount(maker.address, erc20AssetData)
|
||||
.callAsync();
|
||||
expect(transferableAmount).to.bignumber.equal(allowance);
|
||||
});
|
||||
it('should return the correct transferable amount for multiAssetData', async () => {
|
||||
const multiAssetData = await devUtils
|
||||
.encodeMultiAssetData([new BigNumber(1), new BigNumber(1)], [erc20AssetData, erc20AssetData2])
|
||||
.callAsync();
|
||||
const transferableAmount1 = new BigNumber(10);
|
||||
const transferableAmount2 = new BigNumber(5);
|
||||
await erc20Token.setBalance(maker.address, transferableAmount1).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, transferableAmount1).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await erc20Token2.setBalance(maker.address, transferableAmount2).awaitTransactionSuccessAsync();
|
||||
await erc20Token2.approve(erc20Proxy.address, transferableAmount2).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const transferableAmount = await devUtils
|
||||
.getTransferableAssetAmount(maker.address, multiAssetData)
|
||||
.callAsync();
|
||||
expect(transferableAmount).to.bignumber.equal(transferableAmount2);
|
||||
});
|
||||
});
|
||||
describe('getOrderRelevantState', () => {
|
||||
beforeEach(async () => {
|
||||
signedOrder = await maker.signOrderAsync({});
|
||||
});
|
||||
it('should return the correct orderInfo when the order is valid', async () => {
|
||||
const [orderInfo] = await devUtils.getOrderRelevantState(signedOrder, signedOrder.signature).callAsync();
|
||||
expect(orderInfo.orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder));
|
||||
expect(orderInfo.orderStatus).to.equal(OrderStatus.Fillable);
|
||||
expect(orderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return isValidSignature=true when the signature is valid', async () => {
|
||||
const [, , isValidSignature] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(isValidSignature).to.equal(true);
|
||||
});
|
||||
it('should return isValidSignature=false when the signature is invalid', async () => {
|
||||
const invalidSignature = '0x01';
|
||||
const [, , isValidSignature] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, invalidSignature)
|
||||
.callAsync();
|
||||
expect(isValidSignature).to.equal(false);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount of 0 when balances or allowances are insufficient', async () => {
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount of 0 when fee balances/allowances are insufficient', async () => {
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
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 = await devUtils
|
||||
.encodeMultiAssetData([new BigNumber(1), new BigNumber(1)], [erc20AssetData, erc20AssetData2])
|
||||
.callAsync();
|
||||
signedOrder = await maker.signOrderAsync({ makerAssetData: multiAssetData });
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount of 0 when an erc721 asset is duplicated in a multi-asset proxy order', async () => {
|
||||
const multiAssetData = await devUtils
|
||||
.encodeMultiAssetData([new BigNumber(1), new BigNumber(1)], [erc721AssetData, erc721AssetData])
|
||||
.callAsync();
|
||||
signedOrder = await maker.signOrderAsync({ makerAssetData: multiAssetData });
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return the correct fillableTakerAssetAmount when fee balances/allowances are partially sufficient', async () => {
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const divisor = 4;
|
||||
await feeErc20Token
|
||||
.setBalance(maker.address, signedOrder.makerFee.dividedToIntegerBy(divisor))
|
||||
.awaitTransactionSuccessAsync();
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(
|
||||
signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
|
||||
);
|
||||
});
|
||||
it('should return the correct fillableTakerAssetAmount when non-fee balances/allowances are partially sufficient', async () => {
|
||||
const divisor = 4;
|
||||
await erc20Token
|
||||
.setBalance(maker.address, signedOrder.makerAssetAmount.dividedToIntegerBy(divisor))
|
||||
.awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync();
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(
|
||||
signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
|
||||
);
|
||||
});
|
||||
it('should return the correct fillableTakerAssetAmount when balances/allowances of one asset within a multiAssetData are partially sufficient', async () => {
|
||||
const multiAssetData = await devUtils
|
||||
.encodeMultiAssetData([new BigNumber(1), new BigNumber(1)], [erc20AssetData, erc20AssetData2])
|
||||
.callAsync();
|
||||
signedOrder = await maker.signOrderAsync({ makerAssetData: multiAssetData });
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync();
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const divisor = 4;
|
||||
await erc20Token2
|
||||
.setBalance(maker.address, signedOrder.makerAssetAmount.dividedToIntegerBy(divisor))
|
||||
.awaitTransactionSuccessAsync();
|
||||
await erc20Token2
|
||||
.approve(erc20Proxy.address, signedOrder.makerAssetAmount.dividedToIntegerBy(divisor))
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(
|
||||
signedOrder.takerAssetAmount.dividedToIntegerBy(divisor),
|
||||
);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount of 0 when non-fee balances/allowances are insufficient', async () => {
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync();
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount equal to the takerAssetAmount when the order is unfilled and balances/allowances are sufficient', async () => {
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync();
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
|
||||
});
|
||||
it('should return the correct fillableTakerAssetAmount when balances/allowances are partially sufficient and makerAsset=makerFeeAsset', async () => {
|
||||
signedOrder = await maker.signOrderAsync({
|
||||
makerAssetData: feeAssetData,
|
||||
makerAssetAmount: new BigNumber(10),
|
||||
takerAssetAmount: new BigNumber(20),
|
||||
makerFee: new BigNumber(40),
|
||||
});
|
||||
const transferableMakerAssetAmount = new BigNumber(10);
|
||||
await feeErc20Token.setBalance(maker.address, transferableMakerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await feeErc20Token.approve(erc20Proxy.address, transferableMakerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const expectedFillableTakerAssetAmount = transferableMakerAssetAmount
|
||||
.times(signedOrder.takerAssetAmount)
|
||||
.dividedToIntegerBy(signedOrder.makerAssetAmount.plus(signedOrder.makerFee));
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(expectedFillableTakerAssetAmount);
|
||||
});
|
||||
it('should return the correct fillabeTakerassetAmount when makerAsset balances/allowances are sufficient and there are no maker fees', async () => {
|
||||
signedOrder = await maker.signOrderAsync({ makerFee: constants.ZERO_AMOUNT });
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
|
||||
});
|
||||
it('should return a fillableTakerAssetAmount when the remaining takerAssetAmount is less than the transferable amount', async () => {
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync();
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await erc20Token2.setBalance(takerAddress, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token2.approve(erc20Proxy.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await feeErc20Token.setBalance(takerAddress, signedOrder.takerFee).awaitTransactionSuccessAsync();
|
||||
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
const takerAssetFillAmount = signedOrder.takerAssetAmount.dividedToIntegerBy(4);
|
||||
await exchange
|
||||
.fillOrder(signedOrder, takerAssetFillAmount, signedOrder.signature)
|
||||
.awaitTransactionSuccessAsync({ from: takerAddress, value: DeploymentManager.protocolFee });
|
||||
const [, fillableTakerAssetAmount] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(
|
||||
signedOrder.takerAssetAmount.minus(takerAssetFillAmount),
|
||||
);
|
||||
});
|
||||
it('should return correct info even when there are no fees specified', async () => {
|
||||
signedOrder = await maker.signOrderAsync({
|
||||
makerFee: new BigNumber(0),
|
||||
takerFee: new BigNumber(0),
|
||||
makerFeeAssetData: '0x',
|
||||
takerFeeAssetData: '0x',
|
||||
});
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [orderInfo, fillableTakerAssetAmount, isValidSignature] = await devUtils
|
||||
.getOrderRelevantState(signedOrder, signedOrder.signature)
|
||||
.callAsync();
|
||||
expect(orderInfo.orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder));
|
||||
expect(orderInfo.orderStatus).to.equal(OrderStatus.Fillable);
|
||||
expect(orderInfo.orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(fillableTakerAssetAmount).to.bignumber.equal(signedOrder.takerAssetAmount);
|
||||
expect(isValidSignature).to.equal(true);
|
||||
});
|
||||
});
|
||||
describe('getOrderRelevantStates', async () => {
|
||||
it('should return the correct information for multiple orders', async () => {
|
||||
signedOrder = await maker.signOrderAsync();
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync();
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync();
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const signedOrder2 = await maker.signOrderAsync({
|
||||
makerAssetData: erc721AssetData,
|
||||
makerAssetAmount: new BigNumber(1),
|
||||
});
|
||||
const invalidSignature = '0x01';
|
||||
await exchange.cancelOrder(signedOrder2).awaitTransactionSuccessAsync({ from: maker.address });
|
||||
const [ordersInfo, fillableTakerAssetAmounts, isValidSignature] = await devUtils
|
||||
.getOrderRelevantStates([signedOrder, signedOrder2], [signedOrder.signature, invalidSignature])
|
||||
.callAsync();
|
||||
expect(ordersInfo[0].orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder));
|
||||
expect(ordersInfo[1].orderHash).to.equal(orderHashUtils.getOrderHashHex(signedOrder2));
|
||||
expect(ordersInfo[0].orderStatus).to.equal(OrderStatus.Fillable);
|
||||
expect(ordersInfo[1].orderStatus).to.equal(OrderStatus.Cancelled);
|
||||
expect(ordersInfo[0].orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(ordersInfo[1].orderTakerAssetFilledAmount).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(fillableTakerAssetAmounts[0]).to.bignumber.equal(signedOrder.takerAssetAmount);
|
||||
expect(fillableTakerAssetAmounts[1]).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(isValidSignature[0]).to.equal(true);
|
||||
expect(isValidSignature[1]).to.equal(false);
|
||||
});
|
||||
});
|
||||
describe('getSimulatedOrderTransferResults', () => {
|
||||
beforeEach(async () => {
|
||||
signedOrder = await maker.signOrderAsync();
|
||||
});
|
||||
it('should return TakerAssetDataFailed if the takerAsset transfer fails', async () => {
|
||||
const orderTransferResults = await devUtils
|
||||
.getSimulatedOrderTransferResults(signedOrder, takerAddress, signedOrder.takerAssetAmount)
|
||||
.callAsync();
|
||||
expect(orderTransferResults).to.equal(OrderTransferResults.TakerAssetDataFailed);
|
||||
});
|
||||
it('should return MakerAssetDataFailed if the makerAsset transfer fails', async () => {
|
||||
await erc20Token2.setBalance(takerAddress, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token2.approve(erc20Proxy.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
const orderTransferResults = await devUtils
|
||||
.getSimulatedOrderTransferResults(signedOrder, takerAddress, signedOrder.takerAssetAmount)
|
||||
.callAsync();
|
||||
expect(orderTransferResults).to.equal(OrderTransferResults.MakerAssetDataFailed);
|
||||
});
|
||||
it('should return TakerFeeAssetDataFailed if the takerFeeAsset transfer fails', async () => {
|
||||
await erc20Token2.setBalance(takerAddress, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token2.approve(erc20Proxy.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const orderTransferResults = await devUtils
|
||||
.getSimulatedOrderTransferResults(signedOrder, takerAddress, signedOrder.takerAssetAmount)
|
||||
.callAsync();
|
||||
expect(orderTransferResults).to.equal(OrderTransferResults.TakerFeeAssetDataFailed);
|
||||
});
|
||||
it('should return MakerFeeAssetDataFailed if the makerFeeAsset transfer fails', async () => {
|
||||
await erc20Token2.setBalance(takerAddress, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token2.approve(erc20Proxy.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(takerAddress, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
const orderTransferResults = await devUtils
|
||||
.getSimulatedOrderTransferResults(signedOrder, takerAddress, signedOrder.takerAssetAmount)
|
||||
.callAsync();
|
||||
expect(orderTransferResults).to.equal(OrderTransferResults.MakerFeeAssetDataFailed);
|
||||
});
|
||||
it('should return TransfersSuccessful if all transfers succeed', async () => {
|
||||
await erc20Token2.setBalance(takerAddress, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token2.approve(erc20Proxy.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(takerAddress, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const orderTransferResults = await devUtils
|
||||
.getSimulatedOrderTransferResults(signedOrder, takerAddress, signedOrder.takerAssetAmount)
|
||||
.callAsync();
|
||||
expect(orderTransferResults).to.equal(OrderTransferResults.TransfersSuccessful);
|
||||
});
|
||||
it('should return TransfersSuccessful for a partial fill when taker has ample assets for the fill but not for the whole order', async () => {
|
||||
await erc20Token2
|
||||
.setBalance(takerAddress, signedOrder.takerAssetAmount.dividedBy(2))
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token2.approve(erc20Proxy.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(takerAddress, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const orderTransferResults = await devUtils
|
||||
.getSimulatedOrderTransferResults(signedOrder, takerAddress, signedOrder.takerAssetAmount.dividedBy(2))
|
||||
.callAsync();
|
||||
expect(orderTransferResults).to.equal(OrderTransferResults.TransfersSuccessful);
|
||||
});
|
||||
});
|
||||
describe('getSimulatedOrdersTransferResults', async () => {
|
||||
it('should simulate the transfers of each order independently from one another', async () => {
|
||||
// Set balances and allowances to exactly enough to fill a single order
|
||||
await erc20Token2.setBalance(takerAddress, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token2.approve(erc20Proxy.address, signedOrder.takerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await erc20Token.setBalance(maker.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await erc20Token.approve(erc20Proxy.address, signedOrder.makerAssetAmount).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
await feeErc20Token.setBalance(takerAddress, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.takerFee).awaitTransactionSuccessAsync({
|
||||
from: takerAddress,
|
||||
});
|
||||
await feeErc20Token.setBalance(maker.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: owner,
|
||||
});
|
||||
await feeErc20Token.approve(erc20Proxy.address, signedOrder.makerFee).awaitTransactionSuccessAsync({
|
||||
from: maker.address,
|
||||
});
|
||||
const [orderTransferResults1, orderTransferResults2] = await devUtils
|
||||
.getSimulatedOrdersTransferResults(
|
||||
[signedOrder, signedOrder],
|
||||
[takerAddress, takerAddress],
|
||||
[signedOrder.takerAssetAmount, signedOrder.takerAssetAmount],
|
||||
)
|
||||
.callAsync();
|
||||
expect(orderTransferResults1).to.equal(OrderTransferResults.TransfersSuccessful);
|
||||
expect(orderTransferResults2).to.equal(OrderTransferResults.TransfersSuccessful);
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:disable:max-file-line-count
|
@@ -8,7 +8,7 @@ import {
|
||||
MultiAssetProxyContract,
|
||||
StaticCallProxyContract,
|
||||
} from '@0x/contracts-asset-proxy';
|
||||
import { DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { artifacts as devUtilsArtifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { artifacts as ERC1155Artifacts, ERC1155MintableContract } from '@0x/contracts-erc1155';
|
||||
import { artifacts as ERC20Artifacts, DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20';
|
||||
import { artifacts as ERC721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
@@ -196,7 +196,13 @@ export class DeploymentManager {
|
||||
staking.stakingProxy,
|
||||
]);
|
||||
|
||||
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, environment.provider);
|
||||
const devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
||||
devUtilsArtifacts.DevUtils,
|
||||
environment.provider,
|
||||
environment.txDefaults,
|
||||
devUtilsArtifacts,
|
||||
exchange.address,
|
||||
);
|
||||
const assetDataEncoder = new IAssetDataContract(constants.NULL_ADDRESS, environment.provider);
|
||||
|
||||
// Construct the new instance and return it.
|
||||
|
Reference in New Issue
Block a user