merge v2-prototype

This commit is contained in:
Fabio Berger 2018-06-07 12:27:03 +02:00
commit 73429fc720
292 changed files with 2724 additions and 2403 deletions

View File

@ -25,8 +25,12 @@ jobs:
key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }} key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths: paths:
- node_modules/ - node_modules/
- run: node ./node_modules/lerna/bin/lerna.js bootstrap - run: >
- run: yarn build if [ -z "$(git diff --name-only v2-prototype packages/website)" ]; then
yarn build --exclude website
else
yarn build
fi
- save_cache: - save_cache:
key: repo-{{ .Environment.CIRCLE_SHA1 }} key: repo-{{ .Environment.CIRCLE_SHA1 }}
paths: paths:

View File

@ -1,5 +1,14 @@
lib lib
.nyc_output .nyc_output
/packages/0x.js/src/contract_wrappers/generated/
/packages/contracts/src/contract_wrappers/generated/
/packages/contract-wrappers/src/contract_wrappers/generated/
/packages/metacoin/src/contract_wrappers
/packages/fill-scenarios/src/generated_contract_wrappers/
/packages/order-watcher/src/generated_contract_wrappers/
/packages/order-utils/src/generated_contract_wrappers/
/packages/migrations/src/v1/contract_wrappers
/packages/migrations/src/v2/contract_wrappers
/packages/0x.js/test/artifacts /packages/0x.js/test/artifacts
/packages/contracts/src/artifacts /packages/contracts/src/artifacts
/packages/metacoin/artifacts /packages/metacoin/artifacts

View File

@ -46,6 +46,7 @@
"wsrun": "^2.2.0" "wsrun": "^2.2.0"
}, },
"resolutions": { "resolutions": {
"ethereumjs-tx": "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default" "ethereumjs-tx": "0xProject/ethereumjs-tx#fake-tx-include-signature-by-default",
"ethers": "0xproject/ethers.js#eip-838-reasons"
} }
} }

View File

@ -20,8 +20,8 @@
"build:all": "run-p build:umd:prod build:commonjs; exit 0;", "build:all": "run-p build:umd:prod build:commonjs; exit 0;",
"pre_build": "run-s generate_contract_wrappers copy_artifacts", "pre_build": "run-s generate_contract_wrappers copy_artifacts",
"copy_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts", "copy_artifacts": "copyfiles -u 2 './src/compact_artifacts/**/*.json' ./lib/src/compact_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'", "generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers/generated --backend ethers",
"lint": "tslint --project .", "lint": "tslint --project . --exclude **/src/contract_wrappers/generated/**/*",
"test:circleci": "run-s test:coverage", "test:circleci": "run-s test:coverage",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild_and_test": "run-s build test", "rebuild_and_test": "run-s build test",
@ -91,7 +91,6 @@
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"nyc": "^11.0.1", "nyc": "^11.0.1",
"opn-cli": "^3.1.0", "opn-cli": "^3.1.0",
"prettier": "^1.11.1",
"shx": "^0.2.2", "shx": "^0.2.2",
"sinon": "^4.0.0", "sinon": "^4.0.0",
"source-map-support": "^0.5.0", "source-map-support": "^0.5.0",

View File

@ -19,7 +19,6 @@ import { OrderWatcher, OrderWatcherConfig } from '@0xproject/order-watcher';
import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types'; import { ECSignature, Order, Provider, SignedOrder, TransactionReceiptWithDecodedLogs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import { constants } from './utils/constants'; import { constants } from './utils/constants';

View File

@ -1,16 +1,3 @@
import {
BlockParam,
BlockParamLiteral,
ContractAbi,
ContractEventArg,
ExchangeContractErrs,
FilterObject,
LogWithDecodedArgs,
Order,
OrderState,
SignedOrder,
} from '@0xproject/types';
export enum InternalZeroExError { export enum InternalZeroExError {
NoAbiDecoder = 'NO_ABI_DECODER', NoAbiDecoder = 'NO_ABI_DECODER',
ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY', ZrxNotInTokenRegistry = 'ZRX_NOT_IN_TOKEN_REGISTRY',

View File

@ -1,5 +1,3 @@
import { BigNumber } from '@0xproject/utils';
export const constants = { export const constants = {
NULL_ADDRESS: '0x0000000000000000000000000000000000000000', NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
TESTRPC_NETWORK_ID: 50, TESTRPC_NETWORK_ID: 50,

View File

@ -1,14 +1,12 @@
import { ContractWrappers } from '@0xproject/contract-wrappers'; import { ContractWrappers } from '@0xproject/contract-wrappers';
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
import 'make-promises-safe'; import 'make-promises-safe';
import 'mocha'; import 'mocha';
import * as path from 'path';
import * as Sinon from 'sinon';
import { ApprovalContractEventArgs, LogWithDecodedArgs, Order, TokenEvents, ZeroEx } from '../src'; import { ApprovalContractEventArgs, LogWithDecodedArgs, TokenEvents, ZeroEx } from '../src';
import { chaiSetup } from './utils/chai_setup'; import { chaiSetup } from './utils/chai_setup';
import { constants } from './utils/constants'; import { constants } from './utils/constants';
@ -137,6 +135,7 @@ describe('ZeroEx library', () => {
const proxyAddress = zeroEx.proxy.getContractAddress(); const proxyAddress = zeroEx.proxy.getContractAddress();
const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase); const txHash = await zeroEx.token.setUnlimitedProxyAllowanceAsync(zrxTokenAddress, coinbase);
const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash); const txReceiptWithDecodedLogs = await zeroEx.awaitTransactionMinedAsync(txHash);
// tslint:disable-next-line:no-unnecessary-type-assertion
const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ApprovalContractEventArgs>; const log = txReceiptWithDecodedLogs.logs[0] as LogWithDecodedArgs<ApprovalContractEventArgs>;
expect(log.event).to.be.equal(TokenEvents.Approval); expect(log.event).to.be.equal(TokenEvents.Approval);
expect(log.args._owner).to.be.equal(coinbase); expect(log.args._owner).to.be.equal(coinbase);

View File

@ -1,5 +1,4 @@
import { web3Factory } from '@0xproject/dev-utils'; import { web3Factory } from '@0xproject/dev-utils';
import * as fs from 'fs';
import 'make-promises-safe'; import 'make-promises-safe';
import { ZeroEx } from '../src'; import { ZeroEx } from '../src';

View File

@ -1,8 +1,6 @@
import { devConstants } from '@0xproject/dev-utils'; import { devConstants } from '@0xproject/dev-utils';
import { runV1MigrationsAsync } from '@0xproject/migrations'; import { runV1MigrationsAsync } from '@0xproject/migrations';
import * as path from 'path';
import { constants } from './utils/constants';
import { provider } from './utils/web3_wrapper'; import { provider } from './utils/web3_wrapper';
before('migrate contracts', async function(): Promise<void> { before('migrate contracts', async function(): Promise<void> {

View File

@ -1,4 +1,4 @@
import { devConstants, web3Factory } from '@0xproject/dev-utils'; import { web3Factory } from '@0xproject/dev-utils';
import { Provider } from '@0xproject/types'; import { Provider } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';

View File

@ -12,7 +12,7 @@ import * as yargs from 'yargs';
import toSnakeCase = require('to-snake-case'); import toSnakeCase = require('to-snake-case');
import { ContextData, ContractsBackend, Method, ParamKind } from './types'; import { ContextData, ContractsBackend, ParamKind } from './types';
import { utils } from './utils'; import { utils } from './utils';
const ABI_TYPE_CONSTRUCTOR = 'constructor'; const ABI_TYPE_CONSTRUCTOR = 'constructor';

View File

@ -56,7 +56,7 @@ export const utils = {
const componentType = `${component.name}: ${componentValueType}`; const componentType = `${component.name}: ${componentValueType}`;
return componentType; return componentType;
}); });
const tsType = `{${componentsType}}`; const tsType = `{${componentsType.join(';')}}`;
return tsType; return tsType;
} }
throw new Error(`Unknown Solidity type found: ${solType}`); throw new Error(`Unknown Solidity type found: ${solType}`);

View File

@ -17,7 +17,7 @@
"run_mocha": "mocha lib/test/**/*_test.js --bail --exit", "run_mocha": "mocha lib/test/**/*_test.js --bail --exit",
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
"lint": "tslint --project .", "lint": "tslint --project . --exclude **/src/contract_wrappers/**/*",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js" "manual:postpublish": "yarn build; node ./scripts/postpublish.js"
}, },
"license": "Apache-2.0", "license": "Apache-2.0",

View File

@ -44,6 +44,7 @@ export class BaseContract {
const constructorAbiIfExists = _.find( const constructorAbiIfExists = _.find(
abi, abi,
(abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Constructor, (abiDefinition: AbiDefinition) => abiDefinition.type === AbiType.Constructor,
// tslint:disable-next-line:no-unnecessary-type-assertion
) as ConstructorAbi | undefined; ) as ConstructorAbi | undefined;
if (!_.isUndefined(constructorAbiIfExists)) { if (!_.isUndefined(constructorAbiIfExists)) {
return constructorAbiIfExists; return constructorAbiIfExists;
@ -79,8 +80,7 @@ export class BaseContract {
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged // Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
} as any; } as any;
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) { if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
const estimatedGas = await estimateGasAsync(txData); txDataWithDefaults.gas = await estimateGasAsync(txData);
txDataWithDefaults.gas = estimatedGas;
} }
return txDataWithDefaults; return txDataWithDefaults;
} }

View File

@ -1,4 +1,4 @@
import { Order, SignedOrder } from '@0xproject/types'; import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
export interface Client { export interface Client {

View File

@ -1,7 +1,6 @@
import { assert } from '@0xproject/assert'; import { assert } from '@0xproject/assert';
import { schemas } from '@0xproject/json-schemas'; import { schemas } from '@0xproject/json-schemas';
import { SignedOrder } from '@0xproject/types'; import { SignedOrder } from '@0xproject/types';
import * as _ from 'lodash';
import { FeesResponse, OrderbookResponse, TokenPairsItem } from '../types'; import { FeesResponse, OrderbookResponse, TokenPairsItem } from '../types';

View File

@ -15,7 +15,7 @@
"build": "yarn pre_build && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "build": "yarn pre_build && tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"pre_build": "run-s generate_contract_wrappers update_test_artifacts update_compact_artifacts", "pre_build": "run-s generate_contract_wrappers update_test_artifacts update_compact_artifacts",
"generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'", "generate_contract_wrappers": "abi-gen --abis 'src/compact_artifacts/@(Exchange|Token|TokenTransferProxy|EtherToken|TokenRegistry|DummyToken).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated --backend ethers && prettier --write 'src/contract_wrappers/generated/**.ts'",
"lint": "tslint --project .", "lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*",
"test:circleci": "run-s test:coverage", "test:circleci": "run-s test:coverage",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild_and_test": "run-s build test", "rebuild_and_test": "run-s build test",
@ -69,7 +69,6 @@
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"nyc": "^11.0.1", "nyc": "^11.0.1",
"opn-cli": "^3.1.0", "opn-cli": "^3.1.0",
"prettier": "^1.11.1",
"shx": "^0.2.2", "shx": "^0.2.2",
"sinon": "^4.0.0", "sinon": "^4.0.0",
"source-map-support": "^0.5.0", "source-map-support": "^0.5.0",

View File

@ -7,7 +7,7 @@ import {
LogWithDecodedArgs, LogWithDecodedArgs,
RawLog, RawLog,
} from '@0xproject/types'; } from '@0xproject/types';
import { AbiDecoder, intervalUtils } from '@0xproject/utils'; import { intervalUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream'; import { Block, BlockAndLogStreamer } from 'ethereumjs-blockstream';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -185,6 +185,7 @@ export class ContractWrapper {
this._unsubscribe(filterToken, err); this._unsubscribe(filterToken, err);
}); });
} }
// tslint:disable-next-line:no-unused-variable
private _setNetworkId(networkId: number): void { private _setNetworkId(networkId: number): void {
this._networkId = networkId; this._networkId = networkId;
} }

View File

@ -1,6 +1,6 @@
import { schemas } from '@0xproject/json-schemas'; import { schemas } from '@0xproject/json-schemas';
import { LogWithDecodedArgs } from '@0xproject/types'; import { LogWithDecodedArgs } from '@0xproject/types';
import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -181,6 +181,7 @@ export class EtherTokenWrapper extends ContractWrapper {
: networkSpecificArtifact.address; : networkSpecificArtifact.address;
return contractAddressIfExists; return contractAddressIfExists;
} }
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstance(): void { private _invalidateContractInstance(): void {
this.unsubscribeAll(); this.unsubscribeAll();
this._etherTokenContractsByAddress = {}; this._etherTokenContractsByAddress = {};

View File

@ -8,12 +8,10 @@ import {
LogEntry, LogEntry,
LogWithDecodedArgs, LogWithDecodedArgs,
Order, Order,
OrderAddresses,
OrderState, OrderState,
OrderValues,
SignedOrder, SignedOrder,
} from '@0xproject/types'; } from '@0xproject/types';
import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -35,7 +33,6 @@ import { assert } from '../utils/assert';
import { decorators } from '../utils/decorators'; import { decorators } from '../utils/decorators';
import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator'; import { ExchangeTransferSimulator } from '../utils/exchange_transfer_simulator';
import { OrderValidationUtils } from '../utils/order_validation_utils'; import { OrderValidationUtils } from '../utils/order_validation_utils';
import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper'; import { ContractWrapper } from './contract_wrapper';
import { import {
@ -888,6 +885,7 @@ export class ExchangeWrapper extends ContractWrapper {
const contractAddress = this._getContractAddress(artifacts.ZRX, this._zrxContractAddressIfExists); const contractAddress = this._getContractAddress(artifacts.ZRX, this._zrxContractAddressIfExists);
return contractAddress; return contractAddress;
} }
// tslint:disable:no-unused-variable
private _invalidateContractInstances(): void { private _invalidateContractInstances(): void {
this.unsubscribeAll(); this.unsubscribeAll();
delete this._exchangeContractIfExists; delete this._exchangeContractIfExists;
@ -919,6 +917,7 @@ export class ExchangeWrapper extends ContractWrapper {
const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues); const orderHashHex = await exchangeInstance.getOrderHash.callAsync(orderAddresses, orderValues);
return orderHashHex; return orderHashHex;
} }
// tslint:enable:no-unused-variable
private async _getExchangeContractAsync(): Promise<ExchangeContract> { private async _getExchangeContractAsync(): Promise<ExchangeContract> {
if (!_.isUndefined(this._exchangeContractIfExists)) { if (!_.isUndefined(this._exchangeContractIfExists)) {
return this._exchangeContractIfExists; return this._exchangeContractIfExists;

View File

@ -108,6 +108,7 @@ export class TokenRegistryWrapper extends ContractWrapper {
const contractAddress = this._getContractAddress(artifacts.TokenRegistry, this._contractAddressIfExists); const contractAddress = this._getContractAddress(artifacts.TokenRegistry, this._contractAddressIfExists);
return contractAddress; return contractAddress;
} }
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstance(): void { private _invalidateContractInstance(): void {
delete this._tokenRegistryContractIfExists; delete this._tokenRegistryContractIfExists;
} }

View File

@ -49,6 +49,7 @@ export class TokenTransferProxyWrapper extends ContractWrapper {
const contractAddress = this._getContractAddress(artifacts.TokenTransferProxy, this._contractAddressIfExists); const contractAddress = this._getContractAddress(artifacts.TokenTransferProxy, this._contractAddressIfExists);
return contractAddress; return contractAddress;
} }
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstance(): void { private _invalidateContractInstance(): void {
delete this._tokenTransferProxyContractIfExists; delete this._tokenTransferProxyContractIfExists;
} }

View File

@ -1,6 +1,6 @@
import { schemas } from '@0xproject/json-schemas'; import { schemas } from '@0xproject/json-schemas';
import { LogWithDecodedArgs } from '@0xproject/types'; import { LogWithDecodedArgs } from '@0xproject/types';
import { AbiDecoder, BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -414,6 +414,7 @@ export class TokenWrapper extends ContractWrapper {
); );
return logs; return logs;
} }
// tslint:disable-next-line:no-unused-variable
private _invalidateContractInstances(): void { private _invalidateContractInstances(): void {
this.unsubscribeAll(); this.unsubscribeAll();
this._tokenContractsByAddress = {}; this._tokenContractsByAddress = {};

View File

@ -2,11 +2,7 @@ import { BigNumber } from '@0xproject/utils';
import { import {
BlockParam, BlockParam,
BlockParamLiteral,
ContractAbi,
ContractEventArg, ContractEventArg,
ExchangeContractErrs,
FilterObject,
LogEntryEvent, LogEntryEvent,
LogWithDecodedArgs, LogWithDecodedArgs,
Order, Order,

View File

@ -1,12 +1,11 @@
import { assert as sharedAssert } from '@0xproject/assert'; import { assert as sharedAssert } from '@0xproject/assert';
// We need those two unused imports because they're actually used by sharedAssert which gets injected here // We need those two unused imports because they're actually used by sharedAssert which gets injected here
// tslint:disable-next-line:no-unused-variable // tslint:disable:no-unused-variable
import { Schema } from '@0xproject/json-schemas'; import { Schema } from '@0xproject/json-schemas';
// tslint:disable-next-line:no-unused-variable
import { ECSignature } from '@0xproject/types'; import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash'; // tslint:enable:no-unused-variable
import { isValidSignature } from '@0xproject/order-utils'; import { isValidSignature } from '@0xproject/order-utils';

View File

@ -1,6 +1,5 @@
import { BlockParamLiteral, ExchangeContractErrs } from '@0xproject/types'; import { BlockParamLiteral, ExchangeContractErrs } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { TokenWrapper } from '../contract_wrappers/token_wrapper'; import { TokenWrapper } from '../contract_wrappers/token_wrapper';
import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store'; import { BalanceAndProxyAllowanceLazyStore } from '../stores/balance_proxy_allowance_lazy_store';

View File

@ -1,3 +1,4 @@
// tslint:disable:no-unused-variable
import { import {
ConstructorAbi, ConstructorAbi,
ContractAbi, ContractAbi,
@ -7,6 +8,7 @@ import {
LogEntry, LogEntry,
MethodAbi, MethodAbi,
} from '@0xproject/types'; } from '@0xproject/types';
// tslint:enable:no-unused-variable
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
import * as jsSHA3 from 'js-sha3'; import * as jsSHA3 from 'js-sha3';
import * as _ from 'lodash'; import * as _ from 'lodash';

View File

@ -4,7 +4,7 @@ import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
import { ContractWrappersError, TradeSide, TransferType } from '../types'; import { TradeSide, TransferType } from '../types';
import { constants } from '../utils/constants'; import { constants } from '../utils/constants';
import { utils } from '../utils/utils'; import { utils } from '../utils/utils';

View File

@ -1,5 +1,4 @@
import { web3Factory } from '@0xproject/dev-utils'; import { web3Factory } from '@0xproject/dev-utils';
import * as fs from 'fs';
import 'make-promises-safe'; import 'make-promises-safe';
import { ContractWrappers } from '../src'; import { ContractWrappers } from '../src';

View File

@ -1,4 +1,4 @@
import { BlockchainLifecycle, callbackErrorReporter, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { DoneCallback } from '@0xproject/types'; import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';

View File

@ -1,4 +1,4 @@
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BlockParamLiteral, Token } from '@0xproject/types'; import { BlockParamLiteral, Token } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';

View File

@ -1,11 +1,10 @@
import { BlockchainLifecycle, callbackErrorReporter, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios'; import { FillScenarios } from '@0xproject/fill-scenarios';
import { getOrderHashHex } from '@0xproject/order-utils'; import { getOrderHashHex } from '@0xproject/order-utils';
import { BlockParamLiteral, DoneCallback, OrderState } from '@0xproject/types'; import { BlockParamLiteral, DoneCallback, OrderState } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash';
import 'make-promises-safe'; import 'make-promises-safe';
import 'mocha'; import 'mocha';

View File

@ -1,8 +1,6 @@
import { devConstants } from '@0xproject/dev-utils'; import { devConstants } from '@0xproject/dev-utils';
import { runV1MigrationsAsync } from '@0xproject/migrations'; import { runV1MigrationsAsync } from '@0xproject/migrations';
import * as path from 'path';
import { constants } from './utils/constants';
import { provider } from './utils/web3_wrapper'; import { provider } from './utils/web3_wrapper';
before('migrate contracts', async function(): Promise<void> { before('migrate contracts', async function(): Promise<void> {

View File

@ -1,4 +1,4 @@
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { FillScenarios } from '@0xproject/fill-scenarios'; import { FillScenarios } from '@0xproject/fill-scenarios';
import { OrderError } from '@0xproject/order-utils'; import { OrderError } from '@0xproject/order-utils';
import { BlockParamLiteral } from '@0xproject/types'; import { BlockParamLiteral } from '@0xproject/types';
@ -7,7 +7,7 @@ import * as chai from 'chai';
import 'make-promises-safe'; import 'make-promises-safe';
import * as Sinon from 'sinon'; import * as Sinon from 'sinon';
import { ContractWrappers, ContractWrappersError, ExchangeContractErrs, SignedOrder, Token } from '../src'; import { ContractWrappers, ExchangeContractErrs, SignedOrder, Token } from '../src';
import { TradeSide, TransferType } from '../src/types'; import { TradeSide, TransferType } from '../src/types';
import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator'; import { ExchangeTransferSimulator } from '../src/utils/exchange_transfer_simulator';
import { OrderValidationUtils } from '../src/utils/order_validation_utils'; import { OrderValidationUtils } from '../src/utils/order_validation_utils';

View File

@ -1,4 +1,4 @@
import { BlockchainLifecycle, callbackErrorReporter, devConstants } from '@0xproject/dev-utils'; import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { DoneCallback } from '@0xproject/types'; import { DoneCallback } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';

View File

@ -1,4 +1,4 @@
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { schemas, SchemaValidator } from '@0xproject/json-schemas'; import { schemas, SchemaValidator } from '@0xproject/json-schemas';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';

View File

@ -1,4 +1,4 @@
import { BlockchainLifecycle, callbackErrorReporter, devConstants } from '@0xproject/dev-utils'; import { BlockchainLifecycle, callbackErrorReporter } from '@0xproject/dev-utils';
import { EmptyWalletSubprovider } from '@0xproject/subproviders'; import { EmptyWalletSubprovider } from '@0xproject/subproviders';
import { DoneCallback, Provider } from '@0xproject/types'; import { DoneCallback, Provider } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
@ -218,7 +218,6 @@ describe('TokenWrapper', () => {
describe('With provider without accounts', () => { describe('With provider without accounts', () => {
let zeroExContractWithoutAccounts: ContractWrappers; let zeroExContractWithoutAccounts: ContractWrappers;
before(async () => { before(async () => {
const hasAddresses = false;
const emptyWalletProvider = addEmptyWalletSubprovider(provider); const emptyWalletProvider = addEmptyWalletSubprovider(provider);
zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config); zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config);
}); });
@ -361,7 +360,6 @@ describe('TokenWrapper', () => {
describe('With provider without accounts', () => { describe('With provider without accounts', () => {
let zeroExContractWithoutAccounts: ContractWrappers; let zeroExContractWithoutAccounts: ContractWrappers;
before(async () => { before(async () => {
const hasAddresses = false;
const emptyWalletProvider = addEmptyWalletSubprovider(provider); const emptyWalletProvider = addEmptyWalletSubprovider(provider);
zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config); zeroExContractWithoutAccounts = new ContractWrappers(emptyWalletProvider, config);
}); });

View File

@ -1,4 +1,4 @@
import { devConstants, web3Factory } from '@0xproject/dev-utils'; import { web3Factory } from '@0xproject/dev-utils';
import { Provider } from '@0xproject/types'; import { Provider } from '@0xproject/types';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';

View File

@ -2,8 +2,8 @@
* This file is auto-generated using abi-gen. Don't edit directly. * This file is auto-generated using abi-gen. Don't edit directly.
* Templates can be found at https://github.com/0xProject/0x-monorepo/tree/development/packages/contract_templates. * Templates can be found at https://github.com/0xProject/0x-monorepo/tree/development/packages/contract_templates.
*/ */
// tslint:disable:no-consecutive-blank-lines ordered-imports // tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma whitespace
// tslint:disable-next-line:no-unused-variable // tslint:disable:no-unused-variable
import { BaseContract } from '@0xproject/base-contract'; import { BaseContract } from '@0xproject/base-contract';
import { ContractArtifact } from '@0xproject/sol-compiler'; import { ContractArtifact } from '@0xproject/sol-compiler';
import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, DecodedLogArgs, MethodAbi, Provider, TxData, TxDataPayable } from 'ethereum-types'; import { BlockParam, BlockParamLiteral, CallData, ContractAbi, DataItem, DecodedLogArgs, MethodAbi, Provider, TxData, TxDataPayable } from 'ethereum-types';
@ -11,6 +11,7 @@ import { BigNumber, classUtils, logUtils, promisify } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as ethers from 'ethers'; import * as ethers from 'ethers';
import * as _ from 'lodash'; import * as _ from 'lodash';
// tslint:enable:no-unused-variable
{{#if events}} {{#if events}}
export type {{contractName}}ContractEventArgs = export type {{contractName}}ContractEventArgs =
@ -83,7 +84,7 @@ export class {{contractName}}Contract extends BaseContract {
return contractInstance; return contractInstance;
} }
constructor(abi: ContractAbi, address: string, provider: Provider, txDefaults?: Partial<TxData>) { constructor(abi: ContractAbi, address: string, provider: Provider, txDefaults?: Partial<TxData>) {
super("{{contractName}}", abi, address, provider, txDefaults); super('{{contractName}}', abi, address, provider, txDefaults);
classUtils.bindAll(this, ['_ethersInterfacesByFunctionSignature', 'address', 'abi', '_web3Wrapper']); classUtils.bindAll(this, ['_ethersInterfacesByFunctionSignature', 'address', 'abi', '_web3Wrapper']);
} }
} // tslint:disable:max-file-line-count } // tslint:disable:max-file-line-count

View File

@ -18,7 +18,7 @@ async callAsync(
data: encodedData, data: encodedData,
}, },
self._web3Wrapper.getContractDefaults(), self._web3Wrapper.getContractDefaults(),
) );
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock); const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
let resultArray = ethersFunction.parse(rawCallResult); let resultArray = ethersFunction.parse(rawCallResult);
const outputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).outputs; const outputAbi = (_.find(self.abi, {name: '{{this.name}}'}) as MethodAbi).outputs;

View File

@ -63,3 +63,12 @@ yarn lint
```bash ```bash
yarn test yarn test
``` ```
### Run Tests Against Geth
Follow the instructions in the README for the devnet package to start the
devnet.
```bash
TEST_PROVIDER=geth yarn test
```

View File

@ -22,8 +22,8 @@
"compile": "sol-compiler", "compile": "sol-compiler",
"clean": "shx rm -rf lib src/generated_contract_wrappers", "clean": "shx rm -rf lib src/generated_contract_wrappers",
"generate_contract_wrappers": "generate_contract_wrappers":
"abi-gen --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'", "abi-gen --abis ${npm_package_config_abis} --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers/generated --backend ethers",
"lint": "tslint --project .", "lint": "tslint --project . --exclude **/src/contract_wrappers/**/* --exclude **/lib/**/*",
"coverage:report:text": "istanbul report text", "coverage:report:text": "istanbul report text",
"coverage:report:html": "istanbul report html && open coverage/index.html", "coverage:report:html": "istanbul report html && open coverage/index.html",
"coverage:report:lcov": "istanbul report lcov", "coverage:report:lcov": "istanbul report lcov",
@ -61,7 +61,6 @@
"make-promises-safe": "^1.1.0", "make-promises-safe": "^1.1.0",
"mocha": "^4.0.1", "mocha": "^4.0.1",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"prettier": "^1.11.1",
"shx": "^0.2.2", "shx": "^0.2.2",
"solc": "^0.4.24", "solc": "^0.4.24",
"tslint": "5.8.0", "tslint": "5.8.0",

View File

@ -50,7 +50,7 @@ contract MixinExchangeCore is
////// Core exchange functions ////// ////// Core exchange functions //////
/// @dev Cancels all orders reated by sender with a salt less than or equal to the specified salt value. /// @dev Cancels all orders created by sender with a salt less than or equal to the specified salt value.
/// @param salt Orders created with a salt less or equal to this value will be cancelled. /// @param salt Orders created with a salt less or equal to this value will be cancelled.
function cancelOrdersUpTo(uint256 salt) function cancelOrdersUpTo(uint256 salt)
external external

View File

@ -0,0 +1,63 @@
import * as chai from 'chai';
import * as _ from 'lodash';
import { constants } from './constants';
const expect = chai.expect;
function _expectEitherErrorAsync<T>(p: Promise<T>, error1: string, error2: string): PromiseLike<void> {
return expect(p)
.to.be.rejected()
.then(e => {
expect(e).to.satisfy(
(err: Error) => _.includes(err.message, error1) || _.includes(err.message, error2),
`expected promise to reject with error message that includes "${error1}" or "${error2}", but got: ` +
`"${e.message}"\n`,
);
});
}
/**
* Rejects if the given Promise does not reject with an error indicating
* insufficient funds.
* @param p the Promise which is expected to reject
* @returns a new Promise which will reject if the conditions are not met and
* otherwise resolve with no value.
*/
export function expectInsufficientFundsAsync<T>(p: Promise<T>): PromiseLike<void> {
return _expectEitherErrorAsync(p, 'insufficient funds', "sender doesn't have enough funds");
}
/**
* Rejects if the given Promise does not reject with a "revert" error or the
* given otherError.
* @param p the Promise which is expected to reject
* @param otherError the other error which is accepted as a valid reject error.
* @returns a new Promise which will reject if the conditions are not met and
* otherwise resolve with no value.
*/
export function expectRevertOrOtherErrorAsync<T>(p: Promise<T>, otherError: string): PromiseLike<void> {
return _expectEitherErrorAsync(p, constants.REVERT, otherError);
}
/**
* Rejects if the given Promise does not reject with a "revert" or "always
* failing transaction" error.
* @param p the Promise which is expected to reject
* @returns a new Promise which will reject if the conditions are not met and
* otherwise resolve with no value.
*/
export function expectRevertOrAlwaysFailingTransactionAsync<T>(p: Promise<T>): PromiseLike<void> {
return expectRevertOrOtherErrorAsync(p, 'always failing transaction');
}
/**
* Rejects if the given Promise does not reject with a "revert" or "Contract
* call failed" error.
* @param p the Promise which is expected to reject
* @returns a new Promise which will reject if the conditions are not met and
* otherwise resolve with no value.
*/
export function expectRevertOrContractCallFailedAsync<T>(p: Promise<T>): PromiseLike<void> {
return expectRevertOrOtherErrorAsync<T>(p, 'Contract call failed');
}

View File

@ -19,6 +19,13 @@ const TESTRPC_PRIVATE_KEYS_STRINGS = [
export const constants = { export const constants = {
INVALID_OPCODE: 'invalid opcode', INVALID_OPCODE: 'invalid opcode',
REVERT: 'revert', REVERT: 'revert',
LIB_BYTES_GT_ZERO_LENGTH_REQUIRED: 'Length must be greater than 0.',
LIB_BYTES_GTE_4_LENGTH_REQUIRED: 'Length must be greater than or equal to 4.',
LIB_BYTES_GTE_20_LENGTH_REQUIRED: 'Length must be greater than or equal to 20.',
LIB_BYTES_GTE_32_LENGTH_REQUIRED: 'Length must be greater than or equal to 32.',
LIB_BYTES_INDEX_OUT_OF_BOUNDS: 'Specified array index is out of bounds.',
ERC20_INSUFFICIENT_BALANCE: 'Insufficient balance to complete transfer.',
ERC20_INSUFFICIENT_ALLOWANCE: 'Insufficient allowance to complete transfer.',
TESTRPC_NETWORK_ID: 50, TESTRPC_NETWORK_ID: 50,
AWAIT_TRANSACTION_MINED_MS: 100, AWAIT_TRANSACTION_MINED_MS: 100,
MAX_ETHERTOKEN_WITHDRAW_GAS: 43000, MAX_ETHERTOKEN_WITHDRAW_GAS: 43000,

View File

@ -1,6 +1,5 @@
import { devConstants } from '@0xproject/dev-utils'; import { devConstants } from '@0xproject/dev-utils';
import { CoverageSubprovider, SolCompilerArtifactAdapter } from '@0xproject/sol-cov'; import { CoverageSubprovider, SolCompilerArtifactAdapter } from '@0xproject/sol-cov';
import * as fs from 'fs';
import * as _ from 'lodash'; import * as _ from 'lodash';
let coverageSubprovider: CoverageSubprovider; let coverageSubprovider: CoverageSubprovider;

View File

@ -1,7 +1,7 @@
import { AssetProxyId, SignedOrder } from '@0xproject/types'; import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { LogEntry, Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types'; import { Provider, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { ExchangeContract } from '../generated_contract_wrappers/exchange'; import { ExchangeContract } from '../generated_contract_wrappers/exchange';
@ -60,14 +60,14 @@ export class ExchangeWrapper {
public async fillOrderNoThrowAsync( public async fillOrderNoThrowAsync(
signedOrder: SignedOrder, signedOrder: SignedOrder,
from: string, from: string,
opts: { takerAssetFillAmount?: BigNumber } = {}, opts: { takerAssetFillAmount?: BigNumber; gas?: number } = {},
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount); const params = orderUtils.createFill(signedOrder, opts.takerAssetFillAmount);
const txHash = await this._exchange.fillOrderNoThrow.sendTransactionAsync( const txHash = await this._exchange.fillOrderNoThrow.sendTransactionAsync(
params.order, params.order,
params.takerAssetFillAmount, params.takerAssetFillAmount,
params.signature, params.signature,
{ from }, { from, gas: opts.gas },
); );
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx; return tx;
@ -105,14 +105,14 @@ export class ExchangeWrapper {
public async batchFillOrdersNoThrowAsync( public async batchFillOrdersNoThrowAsync(
orders: SignedOrder[], orders: SignedOrder[],
from: string, from: string,
opts: { takerAssetFillAmounts?: BigNumber[] } = {}, opts: { takerAssetFillAmounts?: BigNumber[]; gas?: number } = {},
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts); const params = formatters.createBatchFill(orders, opts.takerAssetFillAmounts);
const txHash = await this._exchange.batchFillOrdersNoThrow.sendTransactionAsync( const txHash = await this._exchange.batchFillOrdersNoThrow.sendTransactionAsync(
params.orders, params.orders,
params.takerAssetFillAmounts, params.takerAssetFillAmounts,
params.signatures, params.signatures,
{ from }, { from, gas: opts.gas },
); );
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx; return tx;
@ -135,14 +135,14 @@ export class ExchangeWrapper {
public async marketSellOrdersNoThrowAsync( public async marketSellOrdersNoThrowAsync(
orders: SignedOrder[], orders: SignedOrder[],
from: string, from: string,
opts: { takerAssetFillAmount: BigNumber }, opts: { takerAssetFillAmount: BigNumber; gas?: number },
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createMarketSellOrders(orders, opts.takerAssetFillAmount); const params = formatters.createMarketSellOrders(orders, opts.takerAssetFillAmount);
const txHash = await this._exchange.marketSellOrdersNoThrow.sendTransactionAsync( const txHash = await this._exchange.marketSellOrdersNoThrow.sendTransactionAsync(
params.orders, params.orders,
params.takerAssetFillAmount, params.takerAssetFillAmount,
params.signatures, params.signatures,
{ from }, { from, gas: opts.gas },
); );
const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash); const tx = await this._logDecoder.getTxWithDecodedLogsAsync(txHash);
return tx; return tx;

View File

@ -0,0 +1,31 @@
import * as _ from 'lodash';
import { constants } from './constants';
import { web3Wrapper } from './web3_wrapper';
let firstAccount: string | undefined;
/**
* Increases time by the given number of seconds and then mines a block so that
* the current block timestamp has the offset applied.
* @param seconds the number of seconds by which to incrase the time offset.
* @returns a new Promise which will resolve with the new total time offset or
* reject if the time could not be increased.
*/
export async function increaseTimeAndMineBlockAsync(seconds: number): Promise<number> {
if (_.isUndefined(firstAccount)) {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
firstAccount = accounts[0];
}
const offset = await web3Wrapper.increaseTimeAsync(seconds);
// Note: we need to send a transaction after increasing time so
// that a block is actually mined. The contract looks at the
// last mined block for the timestamp.
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({ from: firstAccount, to: firstAccount, value: 0 }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
return offset;
}

View File

@ -39,6 +39,7 @@ export class LogDecoder {
} }
public decodeLogOrThrow<ArgsType extends DecodedLogArgs>(log: LogEntry): LogWithDecodedArgs<ArgsType> | RawLog { public decodeLogOrThrow<ArgsType extends DecodedLogArgs>(log: LogEntry): LogWithDecodedArgs<ArgsType> | RawLog {
const logWithDecodedArgsOrLog = this._abiDecoder.tryToDecodeLogOrNoop(log); const logWithDecodedArgsOrLog = this._abiDecoder.tryToDecodeLogOrNoop(log);
// tslint:disable-next-line:no-unnecessary-type-assertion
if (_.isUndefined((logWithDecodedArgsOrLog as LogWithDecodedArgs<ArgsType>).args)) { if (_.isUndefined((logWithDecodedArgsOrLog as LogWithDecodedArgs<ArgsType>).args)) {
throw new Error(`Unable to decode log: ${JSON.stringify(log)}`); throw new Error(`Unable to decode log: ${JSON.stringify(log)}`);
} }

View File

@ -1,38 +1,21 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { assetProxyUtils, crypto, orderHashUtils } from '@0xproject/order-utils';
import { AssetProxyId, SignedOrder } from '@0xproject/types'; import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash'; import * as _ from 'lodash';
import { DummyERC20TokenContract } from '../generated_contract_wrappers/dummy_e_r_c20_token';
import { DummyERC721TokenContract } from '../generated_contract_wrappers/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../generated_contract_wrappers/e_r_c20_proxy';
import { ERC721ProxyContract } from '../generated_contract_wrappers/e_r_c721_proxy';
import {
CancelContractEventArgs,
ExchangeContract,
FillContractEventArgs,
} from '../generated_contract_wrappers/exchange';
import { chaiSetup } from '../utils/chai_setup'; import { chaiSetup } from '../utils/chai_setup';
import { constants } from '../utils/constants';
import { ERC20Wrapper } from '../utils/erc20_wrapper'; import { ERC20Wrapper } from '../utils/erc20_wrapper';
import { ERC721Wrapper } from '../utils/erc721_wrapper'; import { ERC721Wrapper } from '../utils/erc721_wrapper';
import { ExchangeWrapper } from '../utils/exchange_wrapper'; import { ExchangeWrapper } from '../utils/exchange_wrapper';
import { OrderFactory } from '../utils/order_factory';
import { import {
ContractName,
ERC20BalancesByOwner, ERC20BalancesByOwner,
ERC721TokenIdsByOwner, ERC721TokenIdsByOwner,
TransferAmountsByMatchOrders as TransferAmounts, TransferAmountsByMatchOrders as TransferAmounts,
} from '../utils/types'; } from '../utils/types';
import { provider, web3Wrapper } from '../utils/web3_wrapper';
chaiSetup.configure(); chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
export class MatchOrderTester { export class MatchOrderTester {
private _exchangeWrapper: ExchangeWrapper; private _exchangeWrapper: ExchangeWrapper;
@ -112,11 +95,6 @@ export class MatchOrderTester {
initialTakerAssetFilledAmountLeft?: BigNumber, initialTakerAssetFilledAmountLeft?: BigNumber,
initialTakerAssetFilledAmountRight?: BigNumber, initialTakerAssetFilledAmountRight?: BigNumber,
): Promise<[ERC20BalancesByOwner, ERC721TokenIdsByOwner]> { ): Promise<[ERC20BalancesByOwner, ERC721TokenIdsByOwner]> {
// Test setup & verify preconditions
const makerAddressLeft = signedOrderLeft.makerAddress;
const makerAddressRight = signedOrderRight.makerAddress;
const feeRecipientAddressLeft = signedOrderLeft.feeRecipientAddress;
const feeRecipientAddressRight = signedOrderRight.feeRecipientAddress;
// Verify Left order preconditions // Verify Left order preconditions
const orderTakerAssetFilledAmountLeft = await this._exchangeWrapper.getTakerAssetFilledAmountAsync( const orderTakerAssetFilledAmountLeft = await this._exchangeWrapper.getTakerAssetFilledAmountAsync(
orderHashUtils.getOrderHashHex(signedOrderLeft), orderHashUtils.getOrderHashHex(signedOrderLeft),

View File

@ -6,7 +6,6 @@ import * as _ from 'lodash';
import { AssetProxyOwnerContract } from '../generated_contract_wrappers/asset_proxy_owner'; import { AssetProxyOwnerContract } from '../generated_contract_wrappers/asset_proxy_owner';
import { MultiSigWalletContract } from '../generated_contract_wrappers/multi_sig_wallet'; import { MultiSigWalletContract } from '../generated_contract_wrappers/multi_sig_wallet';
import { constants } from './constants';
import { LogDecoder } from './log_decoder'; import { LogDecoder } from './log_decoder';
export class MultiSigWrapper { export class MultiSigWrapper {

View File

@ -1,7 +1,6 @@
import { generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils'; import { generatePseudoRandomSalt, orderHashUtils } from '@0xproject/order-utils';
import { Order, SignatureType, SignedOrder } from '@0xproject/types'; import { Order, SignatureType, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import { constants } from './constants'; import { constants } from './constants';
import { signingUtils } from './signing_utils'; import { signingUtils } from './signing_utils';

View File

@ -1,6 +1,5 @@
import { Order, OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types'; import { OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import ethUtil = require('ethereumjs-util');
import { CancelOrder, MatchOrder } from './types'; import { CancelOrder, MatchOrder } from './types';

View File

@ -1,6 +1,5 @@
import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { SignatureType } from '@0xproject/types'; import { SignatureType } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as ethUtil from 'ethereumjs-util'; import * as ethUtil from 'ethereumjs-util';
import { signingUtils } from './signing_utils'; import { signingUtils } from './signing_utils';

View File

@ -1,6 +1,6 @@
import { Order, OrderWithoutExchangeAddress } from '@0xproject/types'; import { OrderWithoutExchangeAddress } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { AbiDefinition, ContractAbi } from 'ethereum-types'; import { AbiDefinition } from 'ethereum-types';
export interface ERC20BalancesByOwner { export interface ERC20BalancesByOwner {
[ownerAddress: string]: { [ownerAddress: string]: {

View File

@ -1,19 +1,53 @@
import { devConstants, env, EnvVars, web3Factory } from '@0xproject/dev-utils'; import { devConstants, env, EnvVars, web3Factory } from '@0xproject/dev-utils';
import { prependSubprovider } from '@0xproject/subproviders'; import { prependSubprovider } from '@0xproject/subproviders';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import { Provider } from 'ethereum-types';
import { coverage } from './coverage'; import { coverage } from './coverage';
export const txDefaults = { enum ProviderType {
Ganache = 'ganache',
Geth = 'geth',
}
let testProvider: ProviderType;
switch (process.env.TEST_PROVIDER) {
case undefined:
testProvider = ProviderType.Ganache;
break;
case 'ganache':
testProvider = ProviderType.Ganache;
break;
case 'geth':
testProvider = ProviderType.Geth;
break;
default:
throw new Error(`Unknown TEST_PROVIDER: ${process.env.TEST_PROVIDER}`);
}
const ganacheTxDefaults = {
from: devConstants.TESTRPC_FIRST_ADDRESS, from: devConstants.TESTRPC_FIRST_ADDRESS,
gas: devConstants.GAS_LIMIT, gas: devConstants.GAS_LIMIT,
}; };
const providerConfigs = { shouldUseInProcessGanache: true }; const gethTxDefaults = {
from: devConstants.TESTRPC_FIRST_ADDRESS,
};
export const txDefaults = testProvider === ProviderType.Ganache ? ganacheTxDefaults : gethTxDefaults;
const gethConfigs = {
shouldUseInProcessGanache: false,
rpcUrl: 'http://localhost:8501',
shouldUseFakeGasEstimate: false,
};
const ganacheConfigs = {
shouldUseInProcessGanache: true,
};
const providerConfigs = testProvider === ProviderType.Ganache ? ganacheConfigs : gethConfigs;
export const provider = web3Factory.getRpcProvider(providerConfigs); export const provider = web3Factory.getRpcProvider(providerConfigs);
const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage); const isCoverageEnabled = env.parseBoolean(EnvVars.SolidityCoverage);
if (isCoverageEnabled) { if (isCoverageEnabled) {
const coverageSubprovider = coverage.getCoverageSubproviderSingleton(); const coverageSubprovider = coverage.getCoverageSubproviderSingleton();
prependSubprovider(provider, coverageSubprovider); prependSubprovider(provider, coverageSubprovider);
} }
export const web3Wrapper = new Web3Wrapper(provider); export const web3Wrapper = new Web3Wrapper(provider);

View File

@ -1,11 +1,10 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import 'make-promises-safe'; import 'make-promises-safe';
import * as Web3 from 'web3';
import { MixinAuthorizableContract } from '../../src/generated_contract_wrappers/mixin_authorizable'; import { MixinAuthorizableContract } from '../../src/generated_contract_wrappers/mixin_authorizable';
import { artifacts } from '../../src/utils/artifacts'; import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup'; import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants'; import { constants } from '../../src/utils/constants';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
@ -44,9 +43,9 @@ describe('Authorizable', () => {
}); });
describe('addAuthorizedAddress', () => { describe('addAuthorizedAddress', () => {
it('should throw if not called by owner', async () => { it('should throw if not called by owner', async () => {
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
authorizable.addAuthorizedAddress.sendTransactionAsync(notOwner, { from: notOwner }), authorizable.addAuthorizedAddress.sendTransactionAsync(notOwner, { from: notOwner }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should allow owner to add an authorized address', async () => { it('should allow owner to add an authorized address', async () => {
await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.awaitTransactionSuccessAsync(
@ -61,9 +60,9 @@ describe('Authorizable', () => {
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS, constants.AWAIT_TRANSACTION_MINED_MS,
); );
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -73,11 +72,11 @@ describe('Authorizable', () => {
await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }), await authorizable.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS, constants.AWAIT_TRANSACTION_MINED_MS,
); );
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { authorizable.removeAuthorizedAddress.sendTransactionAsync(address, {
from: notOwner, from: notOwner,
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should allow owner to remove an authorized address', async () => { it('should allow owner to remove an authorized address', async () => {
@ -96,11 +95,11 @@ describe('Authorizable', () => {
}); });
it('should throw if owner attempts to remove an address that is not authorized', async () => { it('should throw if owner attempts to remove an address that is not authorized', async () => {
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
authorizable.removeAuthorizedAddress.sendTransactionAsync(address, { authorizable.removeAuthorizedAddress.sendTransactionAsync(address, {
from: owner, from: owner,
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });

View File

@ -1,15 +1,14 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils'; import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as Web3 from 'web3';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token'; import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/generated/dummy_e_r_c20_token';
import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c721_token'; import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/generated/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy'; import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/generated/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy'; import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/generated/e_r_c721_proxy';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup'; import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants'; import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@ -144,7 +143,7 @@ describe('Asset Transfer Proxies', () => {
constants.AWAIT_TRANSACTION_MINED_MS, constants.AWAIT_TRANSACTION_MINED_MS,
); );
// Perform a transfer; expect this to fail. // Perform a transfer; expect this to fail.
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
erc20Proxy.transferFrom.sendTransactionAsync( erc20Proxy.transferFrom.sendTransactionAsync(
encodedProxyMetadata, encodedProxyMetadata,
makerAddress, makerAddress,
@ -152,7 +151,7 @@ describe('Asset Transfer Proxies', () => {
transferAmount, transferAmount,
{ from: notAuthorized }, { from: notAuthorized },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if requesting address is not authorized', async () => { it('should throw if requesting address is not authorized', async () => {
@ -160,7 +159,7 @@ describe('Asset Transfer Proxies', () => {
const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10); const amount = new BigNumber(10);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
erc20Proxy.transferFrom.sendTransactionAsync( erc20Proxy.transferFrom.sendTransactionAsync(
encodedProxyMetadata, encodedProxyMetadata,
makerAddress, makerAddress,
@ -170,7 +169,7 @@ describe('Asset Transfer Proxies', () => {
from: notAuthorized, from: notAuthorized,
}, },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -217,7 +216,7 @@ describe('Asset Transfer Proxies', () => {
const toAddresses = _.times(numTransfers, () => takerAddress); const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => amount); const amounts = _.times(numTransfers, () => amount);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
erc20Proxy.batchTransferFrom.sendTransactionAsync( erc20Proxy.batchTransferFrom.sendTransactionAsync(
assetMetadata, assetMetadata,
fromAddresses, fromAddresses,
@ -225,7 +224,7 @@ describe('Asset Transfer Proxies', () => {
amounts, amounts,
{ from: notAuthorized }, { from: notAuthorized },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -247,7 +246,6 @@ describe('Asset Transfer Proxies', () => {
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(1); const amount = new BigNumber(1);
await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.transferFrom.sendTransactionAsync( await erc721Proxy.transferFrom.sendTransactionAsync(
@ -274,9 +272,8 @@ describe('Asset Transfer Proxies', () => {
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0); const amount = new BigNumber(0);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync( erc721Proxy.transferFrom.sendTransactionAsync(
encodedProxyMetadata, encodedProxyMetadata,
makerAddress, makerAddress,
@ -284,7 +281,7 @@ describe('Asset Transfer Proxies', () => {
amount, amount,
{ from: exchangeAddress }, { from: exchangeAddress },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if transferring > 1 amount of a token', async () => { it('should throw if transferring > 1 amount of a token', async () => {
@ -297,9 +294,8 @@ describe('Asset Transfer Proxies', () => {
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId); const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress); expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(500); const amount = new BigNumber(500);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync( erc721Proxy.transferFrom.sendTransactionAsync(
encodedProxyMetadata, encodedProxyMetadata,
makerAddress, makerAddress,
@ -307,7 +303,7 @@ describe('Asset Transfer Proxies', () => {
amount, amount,
{ from: exchangeAddress }, { from: exchangeAddress },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if allowances are too low', async () => { it('should throw if allowances are too low', async () => {
@ -325,7 +321,7 @@ describe('Asset Transfer Proxies', () => {
); );
// Perform a transfer; expect this to fail. // Perform a transfer; expect this to fail.
const amount = new BigNumber(1); const amount = new BigNumber(1);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
erc20Proxy.transferFrom.sendTransactionAsync( erc20Proxy.transferFrom.sendTransactionAsync(
encodedProxyMetadata, encodedProxyMetadata,
makerAddress, makerAddress,
@ -335,7 +331,7 @@ describe('Asset Transfer Proxies', () => {
from: notAuthorized, from: notAuthorized,
}, },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if requesting address is not authorized', async () => { it('should throw if requesting address is not authorized', async () => {
@ -346,7 +342,7 @@ describe('Asset Transfer Proxies', () => {
); );
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(1); const amount = new BigNumber(1);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync( erc721Proxy.transferFrom.sendTransactionAsync(
encodedProxyMetadata, encodedProxyMetadata,
makerAddress, makerAddress,
@ -354,7 +350,7 @@ describe('Asset Transfer Proxies', () => {
amount, amount,
{ from: notAuthorized }, { from: notAuthorized },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -404,7 +400,7 @@ describe('Asset Transfer Proxies', () => {
const toAddresses = _.times(numTransfers, () => takerAddress); const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => new BigNumber(1)); const amounts = _.times(numTransfers, () => new BigNumber(1));
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.batchTransferFrom.sendTransactionAsync( erc721Proxy.batchTransferFrom.sendTransactionAsync(
assetMetadata, assetMetadata,
fromAddresses, fromAddresses,
@ -412,7 +408,7 @@ describe('Asset Transfer Proxies', () => {
amounts, amounts,
{ from: notAuthorized }, { from: notAuthorized },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });

View File

@ -2,9 +2,7 @@ import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import 'make-promises-safe'; import 'make-promises-safe';
import * as Web3 from 'web3';
import { import {
AssetProxyOwnerContract, AssetProxyOwnerContract,
@ -15,15 +13,20 @@ import {
} from '../src/generated_contract_wrappers/asset_proxy_owner'; } from '../src/generated_contract_wrappers/asset_proxy_owner';
import { MixinAuthorizableContract } from '../src/generated_contract_wrappers/mixin_authorizable'; import { MixinAuthorizableContract } from '../src/generated_contract_wrappers/mixin_authorizable';
import { artifacts } from '../src/utils/artifacts'; import { artifacts } from '../src/utils/artifacts';
import {
expectRevertOrAlwaysFailingTransactionAsync,
expectRevertOrContractCallFailedAsync,
} from '../src/utils/assertions';
import { chaiSetup } from '../src/utils/chai_setup'; import { chaiSetup } from '../src/utils/chai_setup';
import { constants } from '../src/utils/constants'; import { constants } from '../src/utils/constants';
import { increaseTimeAndMineBlockAsync } from '../src/utils/increase_time';
import { MultiSigWrapper } from '../src/utils/multi_sig_wrapper'; import { MultiSigWrapper } from '../src/utils/multi_sig_wrapper';
import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper';
chaiSetup.configure(); chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// tslint:disable:no-unnecessary-type-assertion
describe('AssetProxyOwner', () => { describe('AssetProxyOwner', () => {
let owners: string[]; let owners: string[];
let authorized: string; let authorized: string;
@ -101,7 +104,7 @@ describe('AssetProxyOwner', () => {
}); });
it('should throw if a null address is included in assetProxyContracts', async () => { it('should throw if a null address is included in assetProxyContracts', async () => {
const assetProxyContractAddresses = [erc20Proxy.address, constants.NULL_ADDRESS]; const assetProxyContractAddresses = [erc20Proxy.address, constants.NULL_ADDRESS];
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
AssetProxyOwnerContract.deployFrom0xArtifactAsync( AssetProxyOwnerContract.deployFrom0xArtifactAsync(
artifacts.AssetProxyOwner, artifacts.AssetProxyOwner,
provider, provider,
@ -111,7 +114,7 @@ describe('AssetProxyOwner', () => {
REQUIRED_APPROVALS, REQUIRED_APPROVALS,
SECONDS_TIME_LOCKED, SECONDS_TIME_LOCKED,
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -120,9 +123,9 @@ describe('AssetProxyOwner', () => {
const notRemoveAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData( const notRemoveAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(
owners[0], owners[0],
); );
return expect( return expectRevertOrContractCallFailedAsync(
multiSig.isFunctionRemoveAuthorizedAddress.callAsync(notRemoveAuthorizedAddressData), multiSig.isFunctionRemoveAuthorizedAddress.callAsync(notRemoveAuthorizedAddressData),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should return true if data is for removeAuthorizedAddress', async () => { it('should return true if data is for removeAuthorizedAddress', async () => {
@ -139,9 +142,9 @@ describe('AssetProxyOwner', () => {
describe('registerAssetProxy', () => { describe('registerAssetProxy', () => {
it('should throw if not called by multisig', async () => { it('should throw if not called by multisig', async () => {
const isRegistered = true; const isRegistered = true;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
multiSig.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, isRegistered, { from: owners[0] }), multiSig.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, isRegistered, { from: owners[0] }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should register an address if called by multisig after timelock', async () => { it('should register an address if called by multisig after timelock', async () => {
@ -156,11 +159,12 @@ describe('AssetProxyOwner', () => {
registerAssetProxyData, registerAssetProxyData,
owners[0], owners[0],
); );
const log = submitTxRes.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; const log = submitTxRes.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>;
const txId = log.args.transactionId; const txId = log.args.transactionId;
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
await web3Wrapper.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber()); await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());
const executeTxRes = await multiSigWrapper.executeTransactionAsync(txId, owners[0]); const executeTxRes = await multiSigWrapper.executeTransactionAsync(txId, owners[0]);
const registerLog = executeTxRes.logs[0] as LogWithDecodedArgs<AssetProxyRegistrationContractEventArgs>; const registerLog = executeTxRes.logs[0] as LogWithDecodedArgs<AssetProxyRegistrationContractEventArgs>;
@ -187,7 +191,7 @@ describe('AssetProxyOwner', () => {
const txId = log.args.transactionId; const txId = log.args.transactionId;
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
await web3Wrapper.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber()); await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());
const executeTxRes = await multiSigWrapper.executeTransactionAsync(txId, owners[0]); const executeTxRes = await multiSigWrapper.executeTransactionAsync(txId, owners[0]);
const failureLog = executeTxRes.logs[0] as LogWithDecodedArgs<ExecutionFailureContractEventArgs>; const failureLog = executeTxRes.logs[0] as LogWithDecodedArgs<ExecutionFailureContractEventArgs>;
@ -239,7 +243,7 @@ describe('AssetProxyOwner', () => {
await multiSigWrapper.confirmTransactionAsync(erc20AddAuthorizedAddressTxId, owners[1]); await multiSigWrapper.confirmTransactionAsync(erc20AddAuthorizedAddressTxId, owners[1]);
await multiSigWrapper.confirmTransactionAsync(erc721AddAuthorizedAddressTxId, owners[1]); await multiSigWrapper.confirmTransactionAsync(erc721AddAuthorizedAddressTxId, owners[1]);
await web3Wrapper.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber()); await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());
await multiSigWrapper.executeTransactionAsync(registerAssetProxyTxId, owners[0]); await multiSigWrapper.executeTransactionAsync(registerAssetProxyTxId, owners[0]);
await multiSigWrapper.executeTransactionAsync(erc20AddAuthorizedAddressTxId, owners[0]); await multiSigWrapper.executeTransactionAsync(erc20AddAuthorizedAddressTxId, owners[0]);
await multiSigWrapper.executeTransactionAsync(erc721AddAuthorizedAddressTxId, owners[0]); await multiSigWrapper.executeTransactionAsync(erc721AddAuthorizedAddressTxId, owners[0]);
@ -257,9 +261,9 @@ describe('AssetProxyOwner', () => {
const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>;
const txId = log.args.transactionId; const txId = log.args.transactionId;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if tx destination is not registered', async () => { it('should throw if tx destination is not registered', async () => {
@ -276,9 +280,9 @@ describe('AssetProxyOwner', () => {
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if tx data is not for removeAuthorizedAddress', async () => { it('should throw if tx data is not for removeAuthorizedAddress', async () => {
@ -296,9 +300,9 @@ describe('AssetProxyOwner', () => {
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should execute removeAuthorizedAddress for registered address if fully confirmed', async () => { it('should execute removeAuthorizedAddress for registered address if fully confirmed', async () => {
@ -349,9 +353,10 @@ describe('AssetProxyOwner', () => {
const isExecuted = tx[3]; const isExecuted = tx[3];
expect(isExecuted).to.equal(true); expect(isExecuted).to.equal(true);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
}); });
// tslint:enable:no-unnecessary-type-assertion

View File

@ -1,11 +1,12 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber, promisify } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import 'make-promises-safe'; import 'make-promises-safe';
import { WETH9Contract } from '../src/generated_contract_wrappers/weth9'; import { WETH9Contract } from '../src/generated_contract_wrappers/weth9';
import { artifacts } from '../src/utils/artifacts'; import { artifacts } from '../src/utils/artifacts';
import { expectInsufficientFundsAsync, expectRevertOrAlwaysFailingTransactionAsync } from '../src/utils/assertions';
import { chaiSetup } from '../src/utils/chai_setup'; import { chaiSetup } from '../src/utils/chai_setup';
import { constants } from '../src/utils/constants'; import { constants } from '../src/utils/constants';
import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper';
@ -45,9 +46,7 @@ describe('EtherToken', () => {
const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account); const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
const ethToDeposit = initEthBalance.plus(1); const ethToDeposit = initEthBalance.plus(1);
return expect(etherToken.deposit.sendTransactionAsync({ value: ethToDeposit })).to.be.rejectedWith( return expectInsufficientFundsAsync(etherToken.deposit.sendTransactionAsync({ value: ethToDeposit }));
"ender doesn't have enough funds to send tx.",
);
}); });
it('should convert deposited Ether to wrapped Ether tokens', async () => { it('should convert deposited Ether to wrapped Ether tokens', async () => {
@ -76,8 +75,8 @@ describe('EtherToken', () => {
const initEthTokenBalance = await etherToken.balanceOf.callAsync(account); const initEthTokenBalance = await etherToken.balanceOf.callAsync(account);
const ethTokensToWithdraw = initEthTokenBalance.plus(1); const ethTokensToWithdraw = initEthTokenBalance.plus(1);
return expect(etherToken.withdraw.sendTransactionAsync(ethTokensToWithdraw)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, etherToken.withdraw.sendTransactionAsync(ethTokensToWithdraw),
); );
}); });

View File

@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, crypto, orderHashUtils } from '@0xproject/order-utils'; import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { AssetProxyId, SignedOrder } from '@0xproject/types'; import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
@ -18,20 +18,20 @@ import {
FillContractEventArgs, FillContractEventArgs,
} from '../../src/generated_contract_wrappers/exchange'; } from '../../src/generated_contract_wrappers/exchange';
import { artifacts } from '../../src/utils/artifacts'; import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup'; import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants'; import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper'; import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper'; import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { OrderFactory } from '../../src/utils/order_factory'; import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils'; import { ERC20BalancesByOwner } from '../../src/utils/types';
import { ContractName, ERC20BalancesByOwner, OrderStatus } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure(); chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// tslint:disable:no-unnecessary-type-assertion
describe('Exchange core', () => { describe('Exchange core', () => {
let makerAddress: string; let makerAddress: string;
let owner: string; let owner: string;
@ -415,8 +415,8 @@ describe('Exchange core', () => {
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100), 18),
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
}); });
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
); );
}); });
@ -432,8 +432,8 @@ describe('Exchange core', () => {
const invalidSigBuff = Buffer.concat([v, invalidR, invalidS, signatureType]); const invalidSigBuff = Buffer.concat([v, invalidR, invalidS, signatureType]);
const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`; const invalidSigHex = `0x${invalidSigBuff.toString('hex')}`;
signedOrder.signature = invalidSigHex; signedOrder.signature = invalidSigHex;
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
); );
}); });
@ -442,8 +442,8 @@ describe('Exchange core', () => {
makerAssetAmount: new BigNumber(0), makerAssetAmount: new BigNumber(0),
}); });
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
); );
}); });
@ -452,19 +452,19 @@ describe('Exchange core', () => {
takerAssetAmount: new BigNumber(0), takerAssetAmount: new BigNumber(0),
}); });
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
); );
}); });
it('should throw if takerAssetFillAmount is 0', async () => { it('should throw if takerAssetFillAmount is 0', async () => {
signedOrder = orderFactory.newSignedOrder(); signedOrder = orderFactory.newSignedOrder();
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerAssetFillAmount: new BigNumber(0), takerAssetFillAmount: new BigNumber(0),
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if maker erc20Balances are too low to fill order', async () => { it('should throw if maker erc20Balances are too low to fill order', async () => {
@ -472,8 +472,8 @@ describe('Exchange core', () => {
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18),
}); });
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
); );
}); });
@ -481,9 +481,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({ signedOrder = orderFactory.newSignedOrder({
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(100000), 18),
}); });
return expectRevertOrAlwaysFailingTransactionAsync(
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
constants.REVERT,
); );
}); });
@ -494,11 +493,8 @@ describe('Exchange core', () => {
}), }),
constants.AWAIT_TRANSACTION_MINED_MS, constants.AWAIT_TRANSACTION_MINED_MS,
); );
// HACK: `rejectWith` returns a "promise-like" type, but not an actual "Promise", so TSLint return expectRevertOrAlwaysFailingTransactionAsync(
// complains, even though we do need to `await` it. So we disable the TSLint error below. exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
// tslint:disable-next-line:await-promise
await expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(
constants.REVERT,
); );
}); });
@ -509,11 +505,8 @@ describe('Exchange core', () => {
}), }),
constants.AWAIT_TRANSACTION_MINED_MS, constants.AWAIT_TRANSACTION_MINED_MS,
); );
// HACK: `rejectWith` returns a "promise-like" type, but not an actual "Promise", so TSLint return expectRevertOrAlwaysFailingTransactionAsync(
// complains, even though we do need to `await` it. So we disable the TSLint error below. exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
// tslint:disable-next-line:await-promise
await expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith(
constants.REVERT,
); );
}); });
@ -521,16 +514,16 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({ signedOrder = orderFactory.newSignedOrder({
expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)), expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
}); });
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
); );
}); });
it('should throw if no value is filled', async () => { it('should throw if no value is filled', async () => {
signedOrder = orderFactory.newSignedOrder(); signedOrder = orderFactory.newSignedOrder();
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress); await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
return expect(exchangeWrapper.fillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrderAsync(signedOrder, takerAddress),
); );
}); });
}); });
@ -542,8 +535,8 @@ describe('Exchange core', () => {
}); });
it('should throw if not sent by maker', async () => { it('should throw if not sent by maker', async () => {
return expect(exchangeWrapper.cancelOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.cancelOrderAsync(signedOrder, takerAddress),
); );
}); });
@ -552,8 +545,8 @@ describe('Exchange core', () => {
makerAssetAmount: new BigNumber(0), makerAssetAmount: new BigNumber(0),
}); });
return expect(exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
); );
}); });
@ -562,22 +555,21 @@ describe('Exchange core', () => {
takerAssetAmount: new BigNumber(0), takerAssetAmount: new BigNumber(0),
}); });
return expect(exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
); );
}); });
it('should be able to cancel a full order', async () => { it('should be able to cancel a full order', async () => {
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerAssetFillAmount: signedOrder.takerAssetAmount.div(2), takerAssetFillAmount: signedOrder.takerAssetAmount.div(2),
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should log 1 event with correct arguments', async () => { it('should log 1 event with correct arguments', async () => {
const divisor = 2;
const res = await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); const res = await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
expect(res.logs).to.have.length(1); expect(res.logs).to.have.length(1);
@ -593,8 +585,8 @@ describe('Exchange core', () => {
it('should throw if already cancelled', async () => { it('should throw if already cancelled', async () => {
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress); await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
return expect(exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
); );
}); });
@ -602,8 +594,8 @@ describe('Exchange core', () => {
signedOrder = orderFactory.newSignedOrder({ signedOrder = orderFactory.newSignedOrder({
expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)), expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
}); });
return expect(exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress),
); );
}); });
@ -619,11 +611,11 @@ describe('Exchange core', () => {
}); });
const fillTakerAssetAmount2 = new BigNumber(1); const fillTakerAssetAmount2 = new BigNumber(1);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
takerAssetFillAmount: fillTakerAssetAmount2, takerAssetFillAmount: fillTakerAssetAmount2,
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -632,16 +624,16 @@ describe('Exchange core', () => {
const makerEpoch = new BigNumber(1); const makerEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress); await exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress);
const lesserMakerEpoch = new BigNumber(0); const lesserMakerEpoch = new BigNumber(0);
return expect(exchangeWrapper.cancelOrdersUpToAsync(lesserMakerEpoch, makerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.cancelOrdersUpToAsync(lesserMakerEpoch, makerAddress),
); );
}); });
it('should fail to set makerEpoch equal to existing makerEpoch', async () => { it('should fail to set makerEpoch equal to existing makerEpoch', async () => {
const makerEpoch = new BigNumber(1); const makerEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress); await exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress);
return expect(exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress),
); );
}); });
@ -675,7 +667,12 @@ describe('Exchange core', () => {
salt: new BigNumber(3), salt: new BigNumber(3),
}), }),
]; ];
await exchangeWrapper.batchFillOrdersNoThrowAsync(signedOrders, takerAddress); await exchangeWrapper.batchFillOrdersNoThrowAsync(signedOrders, takerAddress, {
// HACK(albrow): We need to hardcode the gas estimate here because
// the Geth gas estimator doesn't work with the way we use
// delegatecall and swallow errors.
gas: 490000,
});
const newBalances = await erc20Wrapper.getBalancesAsync(); const newBalances = await erc20Wrapper.getBalancesAsync();
const fillMakerAssetAmount = signedOrders[2].makerAssetAmount.add(signedOrders[3].makerAssetAmount); const fillMakerAssetAmount = signedOrders[2].makerAssetAmount.add(signedOrders[3].makerAssetAmount);
@ -724,6 +721,7 @@ describe('Exchange core', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress); expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange // Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
// tslint:disable-next-line:no-unused-variable
const res = await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }); const res = await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount });
// Verify post-conditions // Verify post-conditions
const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
@ -749,9 +747,9 @@ describe('Exchange core', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress); expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange // Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }), exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw when taker does not own the token with id takerAssetId', async () => { it('should throw when taker does not own the token with id takerAssetId', async () => {
@ -771,9 +769,9 @@ describe('Exchange core', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.not.equal(takerAddress); expect(initialOwnerTakerAsset).to.be.bignumber.not.equal(takerAddress);
// Call Exchange // Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }), exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw when makerAssetAmount is greater than 1', async () => { it('should throw when makerAssetAmount is greater than 1', async () => {
@ -793,9 +791,9 @@ describe('Exchange core', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress); expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange // Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }), exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw when takerAssetAmount is greater than 1', async () => { it('should throw when takerAssetAmount is greater than 1', async () => {
@ -815,9 +813,9 @@ describe('Exchange core', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress); expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange // Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }), exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw on partial fill', async () => { it('should throw on partial fill', async () => {
@ -837,9 +835,9 @@ describe('Exchange core', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress); expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange // Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }), exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, { takerAssetFillAmount }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should successfully fill order when makerAsset is ERC721 and takerAsset is ERC20', async () => { it('should successfully fill order when makerAsset is ERC721 and takerAsset is ERC20', async () => {
@ -922,4 +920,6 @@ describe('Exchange core', () => {
); );
}); });
}); });
}); // tslint:disable-line:max-file-line-count });
// tslint:disable:max-file-line-count
// tslint:enable:no-unnecessary-type-assertion

View File

@ -3,13 +3,13 @@ import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId } from '@0xproject/types'; import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import * as Web3 from 'web3';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token'; import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy'; import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy'; import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy';
import { TestAssetProxyDispatcherContract } from '../../src/generated_contract_wrappers/test_asset_proxy_dispatcher'; import { TestAssetProxyDispatcherContract } from '../../src/generated_contract_wrappers/test_asset_proxy_dispatcher';
import { artifacts } from '../../src/utils/artifacts'; import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup'; import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants'; import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@ -23,7 +23,6 @@ const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('AssetProxyDispatcher', () => { describe('AssetProxyDispatcher', () => {
let owner: string; let owner: string;
let notOwner: string; let notOwner: string;
let notAuthorized: string;
let makerAddress: string; let makerAddress: string;
let takerAddress: string; let takerAddress: string;
@ -45,7 +44,6 @@ describe('AssetProxyDispatcher', () => {
// Setup accounts & addresses // Setup accounts & addresses
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, notOwner, makerAddress, takerAddress] = accounts); const usedAddresses = ([owner, notOwner, makerAddress, takerAddress] = accounts);
notAuthorized = notOwner;
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner); erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner); erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
@ -177,14 +175,14 @@ describe('AssetProxyDispatcher', () => {
const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20); const proxyAddress = await assetProxyDispatcher.getAssetProxy.callAsync(AssetProxyId.ERC20);
expect(proxyAddress).to.be.equal(erc20Proxy.address); expect(proxyAddress).to.be.equal(erc20Proxy.address);
// The following transaction will throw because the currentAddress is no longer constants.NULL_ADDRESS // The following transaction will throw because the currentAddress is no longer constants.NULL_ADDRESS
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
AssetProxyId.ERC20, AssetProxyId.ERC20,
erc20Proxy.address, erc20Proxy.address,
constants.NULL_ADDRESS, constants.NULL_ADDRESS,
{ from: owner }, { from: owner },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should be able to reset proxy address to NULL', async () => { it('should be able to reset proxy address to NULL', async () => {
@ -218,26 +216,26 @@ describe('AssetProxyDispatcher', () => {
it('should throw if requesting address is not owner', async () => { it('should throw if requesting address is not owner', async () => {
const prevProxyAddress = constants.NULL_ADDRESS; const prevProxyAddress = constants.NULL_ADDRESS;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
AssetProxyId.ERC20, AssetProxyId.ERC20,
erc20Proxy.address, erc20Proxy.address,
prevProxyAddress, prevProxyAddress,
{ from: notOwner }, { from: notOwner },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if attempting to register a proxy to the incorrect id', async () => { it('should throw if attempting to register a proxy to the incorrect id', async () => {
const prevProxyAddress = constants.NULL_ADDRESS; const prevProxyAddress = constants.NULL_ADDRESS;
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.registerAssetProxy.sendTransactionAsync( assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(
AssetProxyId.ERC721, AssetProxyId.ERC721,
erc20Proxy.address, erc20Proxy.address,
prevProxyAddress, prevProxyAddress,
{ from: owner }, { from: owner },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -305,9 +303,8 @@ describe('AssetProxyDispatcher', () => {
// Construct metadata for ERC20 proxy // Construct metadata for ERC20 proxy
const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address); const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress // Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10); const amount = new BigNumber(10);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync( assetProxyDispatcher.publicDispatchTransferFrom.sendTransactionAsync(
encodedProxyMetadata, encodedProxyMetadata,
makerAddress, makerAddress,
@ -315,7 +312,7 @@ describe('AssetProxyDispatcher', () => {
amount, amount,
{ from: owner }, { from: owner },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
}); });

View File

@ -3,7 +3,6 @@ import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types'; import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import ethUtil = require('ethereumjs-util');
import { TestLibsContract } from '../../src/generated_contract_wrappers/test_libs'; import { TestLibsContract } from '../../src/generated_contract_wrappers/test_libs';
import { addressUtils } from '../../src/utils/address_utils'; import { addressUtils } from '../../src/utils/address_utils';

View File

@ -1,23 +1,18 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, crypto } from '@0xproject/order-utils'; import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId, SignedOrder } from '@0xproject/types'; import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash'; import * as _ from 'lodash';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token'; import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/generated/dummy_e_r_c20_token';
import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c721_token'; import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/generated/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy'; import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/generated/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy'; import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/generated/e_r_c721_proxy';
import { import { ExchangeContract } from '../../src/generated_contract_wrappers/generated/exchange';
CancelContractEventArgs,
ExchangeContract,
FillContractEventArgs,
} from '../../src/generated_contract_wrappers/exchange';
import { artifacts } from '../../src/utils/artifacts'; import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup'; import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants'; import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@ -25,13 +20,7 @@ import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
import { ExchangeWrapper } from '../../src/utils/exchange_wrapper'; import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { MatchOrderTester } from '../../src/utils/match_order_tester'; import { MatchOrderTester } from '../../src/utils/match_order_tester';
import { OrderFactory } from '../../src/utils/order_factory'; import { OrderFactory } from '../../src/utils/order_factory';
import { import { ERC20BalancesByOwner, ERC721TokenIdsByOwner, OrderInfo, OrderStatus } from '../../src/utils/types';
ContractName,
ERC20BalancesByOwner,
ERC721TokenIdsByOwner,
OrderInfo,
OrderStatus,
} from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure(); chaiSetup.configure();
@ -64,7 +53,6 @@ describe('matchOrders', () => {
let erc721LeftMakerAssetIds: BigNumber[]; let erc721LeftMakerAssetIds: BigNumber[];
let erc721RightMakerAssetIds: BigNumber[]; let erc721RightMakerAssetIds: BigNumber[];
let erc721TakerAssetIds: BigNumber[];
let defaultERC20MakerAssetAddress: string; let defaultERC20MakerAssetAddress: string;
let defaultERC20TakerAssetAddress: string; let defaultERC20TakerAssetAddress: string;
@ -103,7 +91,6 @@ describe('matchOrders', () => {
const erc721Balances = await erc721Wrapper.getBalancesAsync(); const erc721Balances = await erc721Wrapper.getBalancesAsync();
erc721LeftMakerAssetIds = erc721Balances[makerAddressLeft][erc721Token.address]; erc721LeftMakerAssetIds = erc721Balances[makerAddressLeft][erc721Token.address];
erc721RightMakerAssetIds = erc721Balances[makerAddressRight][erc721Token.address]; erc721RightMakerAssetIds = erc721Balances[makerAddressRight][erc721Token.address];
erc721TakerAssetIds = erc721Balances[takerAddress][erc721Token.address];
// Depoy exchange // Depoy exchange
exchange = await ExchangeContract.deployFrom0xArtifactAsync( exchange = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange, artifacts.Exchange,
@ -639,9 +626,9 @@ describe('matchOrders', () => {
// Cancel left order // Cancel left order
await exchangeWrapper.cancelOrderAsync(signedOrderLeft, signedOrderLeft.makerAddress); await exchangeWrapper.cancelOrderAsync(signedOrderLeft, signedOrderLeft.makerAddress);
// Match orders // Match orders
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress), exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('Should throw if right order is not fillable', async () => { it('Should throw if right order is not fillable', async () => {
@ -665,9 +652,9 @@ describe('matchOrders', () => {
// Cancel right order // Cancel right order
await exchangeWrapper.cancelOrderAsync(signedOrderRight, signedOrderRight.makerAddress); await exchangeWrapper.cancelOrderAsync(signedOrderRight, signedOrderRight.makerAddress);
// Match orders // Match orders
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress), exchangeWrapper.matchOrdersAsync(signedOrderLeft, signedOrderRight, takerAddress),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if there is not a positive spread', async () => { it('should throw if there is not a positive spread', async () => {
@ -689,7 +676,7 @@ describe('matchOrders', () => {
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
}); });
// Match orders // Match orders
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
matchOrderTester.matchOrdersAndVerifyBalancesAsync( matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft, signedOrderLeft,
signedOrderRight, signedOrderRight,
@ -697,7 +684,7 @@ describe('matchOrders', () => {
erc20BalancesByOwner, erc20BalancesByOwner,
erc721TokenIdsByOwner, erc721TokenIdsByOwner,
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if the left maker asset is not equal to the right taker asset ', async () => { it('should throw if the left maker asset is not equal to the right taker asset ', async () => {
@ -719,7 +706,7 @@ describe('matchOrders', () => {
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
}); });
// Match orders // Match orders
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
matchOrderTester.matchOrdersAndVerifyBalancesAsync( matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft, signedOrderLeft,
signedOrderRight, signedOrderRight,
@ -727,7 +714,7 @@ describe('matchOrders', () => {
erc20BalancesByOwner, erc20BalancesByOwner,
erc721TokenIdsByOwner, erc721TokenIdsByOwner,
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if the right maker asset is not equal to the left taker asset', async () => { it('should throw if the right maker asset is not equal to the left taker asset', async () => {
@ -749,7 +736,7 @@ describe('matchOrders', () => {
feeRecipientAddress: feeRecipientAddressRight, feeRecipientAddress: feeRecipientAddressRight,
}); });
// Match orders // Match orders
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
matchOrderTester.matchOrdersAndVerifyBalancesAsync( matchOrderTester.matchOrdersAndVerifyBalancesAsync(
signedOrderLeft, signedOrderLeft,
signedOrderRight, signedOrderRight,
@ -757,7 +744,7 @@ describe('matchOrders', () => {
erc20BalancesByOwner, erc20BalancesByOwner,
erc721TokenIdsByOwner, erc721TokenIdsByOwner,
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should transfer correct amounts when left order maker asset is an ERC721 token', async () => { it('should transfer correct amounts when left order maker asset is an ERC721 token', async () => {

View File

@ -1,7 +1,6 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils'; import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types'; import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import ethUtil = require('ethereumjs-util'); import ethUtil = require('ethereumjs-util');

View File

@ -1,16 +1,15 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { AssetProxyId, Order, OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types'; import { AssetProxyId, OrderWithoutExchangeAddress, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai'; import * as chai from 'chai';
import * as ethUtil from 'ethereumjs-util';
import * as Web3 from 'web3';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token'; import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy'; import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy';
import { ExchangeContract } from '../../src/generated_contract_wrappers/exchange'; import { ExchangeContract } from '../../src/generated_contract_wrappers/exchange';
import { WhitelistContract } from '../../src/generated_contract_wrappers/whitelist'; import { WhitelistContract } from '../../src/generated_contract_wrappers/whitelist';
import { artifacts } from '../../src/utils/artifacts'; import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup'; import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants'; import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@ -18,7 +17,7 @@ import { ExchangeWrapper } from '../../src/utils/exchange_wrapper';
import { OrderFactory } from '../../src/utils/order_factory'; import { OrderFactory } from '../../src/utils/order_factory';
import { orderUtils } from '../../src/utils/order_utils'; import { orderUtils } from '../../src/utils/order_utils';
import { TransactionFactory } from '../../src/utils/transaction_factory'; import { TransactionFactory } from '../../src/utils/transaction_factory';
import { ERC20BalancesByOwner, OrderStatus, SignedTransaction } from '../../src/utils/types'; import { ERC20BalancesByOwner, SignedTransaction } from '../../src/utils/types';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure(); chaiSetup.configure();
@ -126,8 +125,8 @@ describe('Exchange transactions', () => {
}); });
it('should throw if not called by specified sender', async () => { it('should throw if not called by specified sender', async () => {
return expect(exchangeWrapper.executeTransactionAsync(signedTx, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.executeTransactionAsync(signedTx, takerAddress),
); );
}); });
@ -168,8 +167,8 @@ describe('Exchange transactions', () => {
it('should throw if the a 0x transaction with the same transactionHash has already been executed', async () => { it('should throw if the a 0x transaction with the same transactionHash has already been executed', async () => {
await exchangeWrapper.executeTransactionAsync(signedTx, senderAddress); await exchangeWrapper.executeTransactionAsync(signedTx, senderAddress);
return expect(exchangeWrapper.executeTransactionAsync(signedTx, senderAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.executeTransactionAsync(signedTx, senderAddress),
); );
}); });
@ -187,15 +186,15 @@ describe('Exchange transactions', () => {
}); });
it('should throw if not called by specified sender', async () => { it('should throw if not called by specified sender', async () => {
return expect(exchangeWrapper.executeTransactionAsync(signedTx, makerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.executeTransactionAsync(signedTx, makerAddress),
); );
}); });
it('should cancel the order when signed by maker and called by sender', async () => { it('should cancel the order when signed by maker and called by sender', async () => {
await exchangeWrapper.executeTransactionAsync(signedTx, senderAddress); await exchangeWrapper.executeTransactionAsync(signedTx, senderAddress);
return expect(exchangeWrapper.fillOrderAsync(signedOrder, senderAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrderAsync(signedOrder, senderAddress),
); );
}); });
}); });
@ -244,7 +243,7 @@ describe('Exchange transactions', () => {
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder); orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
const salt = generatePseudoRandomSalt(); const salt = generatePseudoRandomSalt();
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
whitelist.fillOrderIfWhitelisted.sendTransactionAsync( whitelist.fillOrderIfWhitelisted.sendTransactionAsync(
orderWithoutExchangeAddress, orderWithoutExchangeAddress,
takerAssetFillAmount, takerAssetFillAmount,
@ -252,7 +251,7 @@ describe('Exchange transactions', () => {
signedOrder.signature, signedOrder.signature,
{ from: takerAddress }, { from: takerAddress },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should revert if taker has not been whitelisted', async () => { it('should revert if taker has not been whitelisted', async () => {
@ -264,7 +263,7 @@ describe('Exchange transactions', () => {
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder); orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
const salt = generatePseudoRandomSalt(); const salt = generatePseudoRandomSalt();
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
whitelist.fillOrderIfWhitelisted.sendTransactionAsync( whitelist.fillOrderIfWhitelisted.sendTransactionAsync(
orderWithoutExchangeAddress, orderWithoutExchangeAddress,
takerAssetFillAmount, takerAssetFillAmount,
@ -272,7 +271,7 @@ describe('Exchange transactions', () => {
signedOrder.signature, signedOrder.signature,
{ from: takerAddress }, { from: takerAddress },
), ),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should fill the order if maker and taker have been whitelisted', async () => { it('should fill the order if maker and taker have been whitelisted', async () => {

View File

@ -1,4 +1,4 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils } from '@0xproject/order-utils'; import { assetProxyUtils } from '@0xproject/order-utils';
import { AssetProxyId, SignedOrder } from '@0xproject/types'; import { AssetProxyId, SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
@ -6,15 +6,14 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
import 'make-promises-safe'; import 'make-promises-safe';
import * as Web3 from 'web3';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token'; import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/generated/dummy_e_r_c20_token';
import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c721_token'; import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/generated/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy'; import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/generated/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy'; import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/generated/e_r_c721_proxy';
import { ExchangeContract } from '../../src/generated_contract_wrappers/exchange'; import { ExchangeContract } from '../../src/generated_contract_wrappers/generated/exchange';
import { TokenRegistryContract } from '../../src/generated_contract_wrappers/token_registry';
import { artifacts } from '../../src/utils/artifacts'; import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup'; import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants'; import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper'; import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
@ -172,8 +171,8 @@ describe('Exchange wrappers', () => {
expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)), expirationTimeSeconds: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
}); });
return expect(exchangeWrapper.fillOrKillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrKillOrderAsync(signedOrder, takerAddress),
); );
}); });
@ -184,8 +183,8 @@ describe('Exchange wrappers', () => {
takerAssetFillAmount: signedOrder.takerAssetAmount.div(2), takerAssetFillAmount: signedOrder.takerAssetAmount.div(2),
}); });
return expect(exchangeWrapper.fillOrKillOrderAsync(signedOrder, takerAddress)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, exchangeWrapper.fillOrKillOrderAsync(signedOrder, takerAddress),
); );
}); });
}); });
@ -197,12 +196,16 @@ describe('Exchange wrappers', () => {
takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(200), 18),
}); });
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2); const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress, { await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress, {
takerAssetFillAmount, takerAssetFillAmount,
// HACK(albrow): We need to hardcode the gas estimate here because
// the Geth gas estimator doesn't work with the way we use
// delegatecall and swallow errors.
gas: 250000,
}); });
const newBalances = await erc20Wrapper.getBalancesAsync(); const newBalances = await erc20Wrapper.getBalancesAsync();
const makerAssetFilledAmount = takerAssetFillAmount const makerAssetFilledAmount = takerAssetFillAmount
.times(signedOrder.makerAssetAmount) .times(signedOrder.makerAssetAmount)
.dividedToIntegerBy(signedOrder.takerAssetAmount); .dividedToIntegerBy(signedOrder.takerAssetAmount);
@ -212,6 +215,7 @@ describe('Exchange wrappers', () => {
const takerFee = signedOrder.takerFee const takerFee = signedOrder.takerFee
.times(makerAssetFilledAmount) .times(makerAssetFilledAmount)
.dividedToIntegerBy(signedOrder.makerAssetAmount); .dividedToIntegerBy(signedOrder.makerAssetAmount);
expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal( expect(newBalances[makerAddress][defaultMakerAssetAddress]).to.be.bignumber.equal(
erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFilledAmount), erc20Balances[makerAddress][defaultMakerAssetAddress].minus(makerAssetFilledAmount),
); );
@ -360,7 +364,13 @@ describe('Exchange wrappers', () => {
expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress); expect(initialOwnerTakerAsset).to.be.bignumber.equal(takerAddress);
// Call Exchange // Call Exchange
const takerAssetFillAmount = signedOrder.takerAssetAmount; const takerAssetFillAmount = signedOrder.takerAssetAmount;
await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress, { takerAssetFillAmount }); await exchangeWrapper.fillOrderNoThrowAsync(signedOrder, takerAddress, {
takerAssetFillAmount,
// HACK(albrow): We need to hardcode the gas estimate here because
// the Geth gas estimator doesn't work with the way we use
// delegatecall and swallow errors.
gas: 270000,
});
// Verify post-conditions // Verify post-conditions
const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId); const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(makerAssetId);
expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress); expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress);
@ -485,11 +495,11 @@ describe('Exchange wrappers', () => {
await exchangeWrapper.fillOrKillOrderAsync(signedOrders[0], takerAddress); await exchangeWrapper.fillOrKillOrderAsync(signedOrders[0], takerAddress);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.batchFillOrKillOrdersAsync(signedOrders, takerAddress, { exchangeWrapper.batchFillOrKillOrdersAsync(signedOrders, takerAddress, {
takerAssetFillAmounts, takerAssetFillAmounts,
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -535,6 +545,10 @@ describe('Exchange wrappers', () => {
await exchangeWrapper.batchFillOrdersNoThrowAsync(signedOrders, takerAddress, { await exchangeWrapper.batchFillOrdersNoThrowAsync(signedOrders, takerAddress, {
takerAssetFillAmounts, takerAssetFillAmounts,
// HACK(albrow): We need to hardcode the gas estimate here because
// the Geth gas estimator doesn't work with the way we use
// delegatecall and swallow errors.
gas: 600000,
}); });
const newBalances = await erc20Wrapper.getBalancesAsync(); const newBalances = await erc20Wrapper.getBalancesAsync();
@ -591,6 +605,10 @@ describe('Exchange wrappers', () => {
const newOrders = [invalidOrder, ...validOrders]; const newOrders = [invalidOrder, ...validOrders];
await exchangeWrapper.batchFillOrdersNoThrowAsync(newOrders, takerAddress, { await exchangeWrapper.batchFillOrdersNoThrowAsync(newOrders, takerAddress, {
takerAssetFillAmounts, takerAssetFillAmounts,
// HACK(albrow): We need to hardcode the gas estimate here because
// the Geth gas estimator doesn't work with the way we use
// delegatecall and swallow errors.
gas: 450000,
}); });
const newBalances = await erc20Wrapper.getBalancesAsync(); const newBalances = await erc20Wrapper.getBalancesAsync();
@ -679,11 +697,11 @@ describe('Exchange wrappers', () => {
orderFactory.newSignedOrder(), orderFactory.newSignedOrder(),
]; ];
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.marketSellOrdersAsync(signedOrders, takerAddress, { exchangeWrapper.marketSellOrdersAsync(signedOrders, takerAddress, {
takerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18), takerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18),
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -753,6 +771,10 @@ describe('Exchange wrappers', () => {
}); });
await exchangeWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, { await exchangeWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, {
takerAssetFillAmount, takerAssetFillAmount,
// HACK(albrow): We need to hardcode the gas estimate here because
// the Geth gas estimator doesn't work with the way we use
// delegatecall and swallow errors.
gas: 600000,
}); });
const newBalances = await erc20Wrapper.getBalancesAsync(); const newBalances = await erc20Wrapper.getBalancesAsync();
@ -768,11 +790,11 @@ describe('Exchange wrappers', () => {
orderFactory.newSignedOrder(), orderFactory.newSignedOrder(),
]; ];
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, { exchangeWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, {
takerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18), takerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18),
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -857,11 +879,11 @@ describe('Exchange wrappers', () => {
orderFactory.newSignedOrder(), orderFactory.newSignedOrder(),
]; ];
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.marketBuyOrdersAsync(signedOrders, takerAddress, { exchangeWrapper.marketBuyOrdersAsync(signedOrders, takerAddress, {
makerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18), makerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18),
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
@ -931,6 +953,10 @@ describe('Exchange wrappers', () => {
}); });
await exchangeWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, { await exchangeWrapper.marketSellOrdersNoThrowAsync(signedOrders, takerAddress, {
takerAssetFillAmount, takerAssetFillAmount,
// HACK(albrow): We need to hardcode the gas estimate here because
// the Geth gas estimator doesn't work with the way we use
// delegatecall and swallow errors.
gas: 600000,
}); });
const newBalances = await erc20Wrapper.getBalancesAsync(); const newBalances = await erc20Wrapper.getBalancesAsync();
@ -946,11 +972,11 @@ describe('Exchange wrappers', () => {
orderFactory.newSignedOrder(), orderFactory.newSignedOrder(),
]; ];
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.marketBuyOrdersNoThrowAsync(signedOrders, takerAddress, { exchangeWrapper.marketBuyOrdersNoThrowAsync(signedOrders, takerAddress, {
makerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18), makerAssetFillAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(1000), 18),
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });

View File

@ -1,15 +1,12 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { AssetProxyId } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import BN = require('bn.js'); import BN = require('bn.js');
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import ethUtil = require('ethereumjs-util'); import ethUtil = require('ethereumjs-util');
import * as Web3 from 'web3';
import { TestLibBytesContract } from '../../src/generated_contract_wrappers/test_lib_bytes'; import { TestLibBytesContract } from '../../src/generated_contract_wrappers/test_lib_bytes';
import { artifacts } from '../../src/utils/artifacts'; import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync, expectRevertOrOtherErrorAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup'; import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants'; import { constants } from '../../src/utils/constants';
import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
@ -19,7 +16,6 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('LibBytes', () => { describe('LibBytes', () => {
let owner: string;
let libBytes: TestLibBytesContract; let libBytes: TestLibBytesContract;
const byteArrayShorterThan32Bytes = '0x012345'; const byteArrayShorterThan32Bytes = '0x012345';
const byteArrayShorterThan20Bytes = byteArrayShorterThan32Bytes; const byteArrayShorterThan20Bytes = byteArrayShorterThan32Bytes;
@ -42,7 +38,6 @@ describe('LibBytes', () => {
before(async () => { before(async () => {
// Setup accounts & addresses // Setup accounts & addresses
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = accounts[0];
testAddress = accounts[1]; testAddress = accounts[1];
// Deploy LibBytes // Deploy LibBytes
libBytes = await TestLibBytesContract.deployFrom0xArtifactAsync(artifacts.TestLibBytes, provider, txDefaults); libBytes = await TestLibBytesContract.deployFrom0xArtifactAsync(artifacts.TestLibBytes, provider, txDefaults);
@ -63,7 +58,10 @@ describe('LibBytes', () => {
describe('popByte', () => { describe('popByte', () => {
it('should revert if length is 0', async () => { it('should revert if length is 0', async () => {
return expect(libBytes.publicPopByte.callAsync(constants.NULL_BYTES)).to.be.rejectedWith(constants.REVERT); return expectRevertOrOtherErrorAsync(
libBytes.publicPopByte.callAsync(constants.NULL_BYTES),
constants.LIB_BYTES_GT_ZERO_LENGTH_REQUIRED,
);
}); });
it('should pop the last byte from the input and return it', async () => { it('should pop the last byte from the input and return it', async () => {
@ -77,8 +75,9 @@ describe('LibBytes', () => {
describe('popAddress', () => { describe('popAddress', () => {
it('should revert if length is less than 20', async () => { it('should revert if length is less than 20', async () => {
return expect(libBytes.publicPopAddress.callAsync(byteArrayShorterThan20Bytes)).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, libBytes.publicPopAddress.callAsync(byteArrayShorterThan20Bytes),
constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED,
); );
}); });
@ -162,16 +161,18 @@ describe('LibBytes', () => {
it('should fail if the byte array is too short to hold an address)', async () => { it('should fail if the byte array is too short to hold an address)', async () => {
const shortByteArray = '0xabcdef'; const shortByteArray = '0xabcdef';
const offset = new BigNumber(0); const offset = new BigNumber(0);
return expect(libBytes.publicReadAddress.callAsync(shortByteArray, offset)).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, libBytes.publicReadAddress.callAsync(shortByteArray, offset),
constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED,
); );
}); });
it('should fail if the length between the offset and end of the byte array is too short to hold an address)', async () => { it('should fail if the length between the offset and end of the byte array is too short to hold an address)', async () => {
const byteArray = ethUtil.addHexPrefix(testAddress); const byteArray = ethUtil.addHexPrefix(testAddress);
const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength); const badOffset = new BigNumber(ethUtil.toBuffer(byteArray).byteLength);
return expect(libBytes.publicReadAddress.callAsync(byteArray, badOffset)).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, libBytes.publicReadAddress.callAsync(byteArray, badOffset),
constants.LIB_BYTES_GTE_20_LENGTH_REQUIRED,
); );
}); });
}); });
@ -206,15 +207,17 @@ describe('LibBytes', () => {
it('should fail if the byte array is too short to hold a bytes32)', async () => { it('should fail if the byte array is too short to hold a bytes32)', async () => {
const offset = new BigNumber(0); const offset = new BigNumber(0);
return expect(libBytes.publicReadBytes32.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, libBytes.publicReadBytes32.callAsync(byteArrayShorterThan32Bytes, offset),
constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED,
); );
}); });
it('should fail if the length between the offset and end of the byte array is too short to hold a bytes32)', async () => { it('should fail if the length between the offset and end of the byte array is too short to hold a bytes32)', async () => {
const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength); const badOffset = new BigNumber(ethUtil.toBuffer(testBytes32).byteLength);
return expect(libBytes.publicReadBytes32.callAsync(testBytes32, badOffset)).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, libBytes.publicReadBytes32.callAsync(testBytes32, badOffset),
constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED,
); );
}); });
}); });
@ -253,8 +256,9 @@ describe('LibBytes', () => {
it('should fail if the byte array is too short to hold a uint256)', async () => { it('should fail if the byte array is too short to hold a uint256)', async () => {
const offset = new BigNumber(0); const offset = new BigNumber(0);
return expect(libBytes.publicReadUint256.callAsync(byteArrayShorterThan32Bytes, offset)).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, libBytes.publicReadUint256.callAsync(byteArrayShorterThan32Bytes, offset),
constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED,
); );
}); });
@ -263,8 +267,9 @@ describe('LibBytes', () => {
const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256); const testUint256AsBuffer = ethUtil.toBuffer(formattedTestUint256);
const byteArray = ethUtil.bufferToHex(testUint256AsBuffer); const byteArray = ethUtil.bufferToHex(testUint256AsBuffer);
const badOffset = new BigNumber(testUint256AsBuffer.byteLength); const badOffset = new BigNumber(testUint256AsBuffer.byteLength);
return expect(libBytes.publicReadUint256.callAsync(byteArray, badOffset)).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, libBytes.publicReadUint256.callAsync(byteArray, badOffset),
constants.LIB_BYTES_GTE_32_LENGTH_REQUIRED,
); );
}); });
}); });
@ -281,10 +286,12 @@ describe('LibBytes', () => {
*/ */
describe('readFirst4', () => { describe('readFirst4', () => {
// AssertionError: expected promise to be rejected with an error including 'revert' but it was fulfilled with '0x08c379a0'
it('should revert if byte array has a length < 4', async () => { it('should revert if byte array has a length < 4', async () => {
const byteArrayLessThan4Bytes = '0x010101'; const byteArrayLessThan4Bytes = '0x010101';
return expect(libBytes.publicReadFirst4.callAsync(byteArrayLessThan4Bytes)).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, libBytes.publicReadFirst4.callAsync(byteArrayLessThan4Bytes),
constants.LIB_BYTES_GTE_4_LENGTH_REQUIRED,
); );
}); });
it('should return the first 4 bytes of a byte array of arbitrary length', async () => { it('should return the first 4 bytes of a byte array of arbitrary length', async () => {

View File

@ -1,26 +1,25 @@
import { BlockchainLifecycle, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import 'make-promises-safe'; import 'make-promises-safe';
import * as Web3 from 'web3';
import { import {
MultiSigWalletWithTimeLockContract, MultiSigWalletWithTimeLockContract,
SubmissionContractEventArgs, SubmissionContractEventArgs,
} from '../src/generated_contract_wrappers/multi_sig_wallet_with_time_lock'; } from '../src/generated_contract_wrappers/multi_sig_wallet_with_time_lock';
import { artifacts } from '../src/utils/artifacts'; import { artifacts } from '../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../src/utils/assertions';
import { chaiSetup } from '../src/utils/chai_setup'; import { chaiSetup } from '../src/utils/chai_setup';
import { constants } from '../src/utils/constants'; import { constants } from '../src/utils/constants';
import { increaseTimeAndMineBlockAsync } from '../src/utils/increase_time';
import { MultiSigWrapper } from '../src/utils/multi_sig_wrapper'; import { MultiSigWrapper } from '../src/utils/multi_sig_wrapper';
import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper';
chaiSetup.configure(); chaiSetup.configure();
const expect = chai.expect; const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// tslint:disable:no-unnecessary-type-assertion
describe('MultiSigWalletWithTimeLock', () => { describe('MultiSigWalletWithTimeLock', () => {
let owners: string[]; let owners: string[];
const REQUIRED_APPROVALS = new BigNumber(2); const REQUIRED_APPROVALS = new BigNumber(2);
@ -69,9 +68,9 @@ describe('MultiSigWalletWithTimeLock', () => {
}); });
it('should throw when not called by wallet', async () => { it('should throw when not called by wallet', async () => {
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
multiSig.changeTimeLock.sendTransactionAsync(SECONDS_TIME_LOCKED, { from: owners[0] }), multiSig.changeTimeLock.sendTransactionAsync(SECONDS_TIME_LOCKED, { from: owners[0] }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw without enough confirmations', async () => { it('should throw without enough confirmations', async () => {
@ -80,10 +79,9 @@ describe('MultiSigWalletWithTimeLock', () => {
const res = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]); const res = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]);
const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>;
const txId = log.args.transactionId; const txId = log.args.transactionId;
return expectRevertOrAlwaysFailingTransactionAsync(
return expect(
multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should set confirmation time with enough confirmations', async () => { it('should set confirmation time with enough confirmations', async () => {
@ -148,14 +146,15 @@ describe('MultiSigWalletWithTimeLock', () => {
txId = log.args.transactionId; txId = log.args.transactionId;
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
}); });
it('should throw if it has enough confirmations but is not past the time lock', async () => { it('should throw if it has enough confirmations but is not past the time lock', async () => {
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should execute if it has enough confirmations and is past the time lock', async () => { it('should execute if it has enough confirmations and is past the time lock', async () => {
await web3Wrapper.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber()); await increaseTimeAndMineBlockAsync(SECONDS_TIME_LOCKED.toNumber());
await web3Wrapper.awaitTransactionSuccessAsync( await web3Wrapper.awaitTransactionSuccessAsync(
await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
constants.AWAIT_TRANSACTION_MINED_MS, constants.AWAIT_TRANSACTION_MINED_MS,
@ -167,3 +166,4 @@ describe('MultiSigWalletWithTimeLock', () => {
}); });
}); });
}); });
// tslint:enable:no-unnecessary-type-assertion

View File

@ -1,14 +1,13 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber, NULL_BYTES } from '@0xproject/utils'; import { BigNumber, NULL_BYTES } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import ethUtil = require('ethereumjs-util'); import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash'; import * as _ from 'lodash';
import 'make-promises-safe'; import 'make-promises-safe';
import * as Web3 from 'web3';
import { TokenRegistryContract } from '../src/generated_contract_wrappers/token_registry'; import { TokenRegistryContract } from '../src/generated_contract_wrappers/token_registry';
import { artifacts } from '../src/utils/artifacts'; import { artifacts } from '../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../src/utils/assertions';
import { chaiSetup } from '../src/utils/chai_setup'; import { chaiSetup } from '../src/utils/chai_setup';
import { constants } from '../src/utils/constants'; import { constants } from '../src/utils/constants';
import { TokenRegWrapper } from '../src/utils/token_registry_wrapper'; import { TokenRegWrapper } from '../src/utils/token_registry_wrapper';
@ -76,7 +75,7 @@ describe('TokenRegistry', () => {
describe('addToken', () => { describe('addToken', () => {
it('should throw when not called by owner', async () => { it('should throw when not called by owner', async () => {
return expect(tokenRegWrapper.addTokenAsync(token1, notOwner)).to.be.rejectedWith(constants.REVERT); return expectRevertOrAlwaysFailingTransactionAsync(tokenRegWrapper.addTokenAsync(token1, notOwner));
}); });
it('should add token metadata when called by owner', async () => { it('should add token metadata when called by owner', async () => {
@ -88,19 +87,19 @@ describe('TokenRegistry', () => {
it('should throw if token already exists', async () => { it('should throw if token already exists', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner); await tokenRegWrapper.addTokenAsync(token1, owner);
return expect(tokenRegWrapper.addTokenAsync(token1, owner)).to.be.rejectedWith(constants.REVERT); return expectRevertOrAlwaysFailingTransactionAsync(tokenRegWrapper.addTokenAsync(token1, owner));
}); });
it('should throw if token address is null', async () => { it('should throw if token address is null', async () => {
return expect(tokenRegWrapper.addTokenAsync(nullToken, owner)).to.be.rejectedWith(constants.REVERT); return expectRevertOrAlwaysFailingTransactionAsync(tokenRegWrapper.addTokenAsync(nullToken, owner));
}); });
it('should throw if name already exists', async () => { it('should throw if name already exists', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner); await tokenRegWrapper.addTokenAsync(token1, owner);
const duplicateNameToken = _.assign({}, token2, { name: token1.name }); const duplicateNameToken = _.assign({}, token2, { name: token1.name });
return expect(tokenRegWrapper.addTokenAsync(duplicateNameToken, owner)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, tokenRegWrapper.addTokenAsync(duplicateNameToken, owner),
); );
}); });
@ -110,8 +109,8 @@ describe('TokenRegistry', () => {
symbol: token1.symbol, symbol: token1.symbol,
}); });
return expect(tokenRegWrapper.addTokenAsync(duplicateSymbolToken, owner)).to.be.rejectedWith( return expectRevertOrAlwaysFailingTransactionAsync(
constants.REVERT, tokenRegWrapper.addTokenAsync(duplicateSymbolToken, owner),
); );
}); });
}); });
@ -137,9 +136,9 @@ describe('TokenRegistry', () => {
describe('setTokenName', () => { describe('setTokenName', () => {
it('should throw when not called by owner', async () => { it('should throw when not called by owner', async () => {
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { from: notOwner }), tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { from: notOwner }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should change the token name when called by owner', async () => { it('should change the token name when called by owner', async () => {
@ -163,25 +162,25 @@ describe('TokenRegistry', () => {
it('should throw if the name already exists', async () => { it('should throw if the name already exists', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner); await tokenRegWrapper.addTokenAsync(token2, owner);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { from: owner }), tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { from: owner }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if token does not exist', async () => { it('should throw if token does not exist', async () => {
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.setTokenName.sendTransactionAsync(nullToken.address, token2.name, { from: owner }), tokenReg.setTokenName.sendTransactionAsync(nullToken.address, token2.name, { from: owner }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
describe('setTokenSymbol', () => { describe('setTokenSymbol', () => {
it('should throw when not called by owner', async () => { it('should throw when not called by owner', async () => {
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, { tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, {
from: notOwner, from: notOwner,
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should change the token symbol when called by owner', async () => { it('should change the token symbol when called by owner', async () => {
@ -203,28 +202,28 @@ describe('TokenRegistry', () => {
it('should throw if the symbol already exists', async () => { it('should throw if the symbol already exists', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner); await tokenRegWrapper.addTokenAsync(token2, owner);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, { tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, {
from: owner, from: owner,
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if token does not exist', async () => { it('should throw if token does not exist', async () => {
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.setTokenSymbol.sendTransactionAsync(nullToken.address, token2.symbol, { tokenReg.setTokenSymbol.sendTransactionAsync(nullToken.address, token2.symbol, {
from: owner, from: owner,
}), }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
describe('removeToken', () => { describe('removeToken', () => {
it('should throw if not called by owner', async () => { it('should throw if not called by owner', async () => {
const index = new BigNumber(0); const index = new BigNumber(0);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.removeToken.sendTransactionAsync(token1.address, index, { from: notOwner }), tokenReg.removeToken.sendTransactionAsync(token1.address, index, { from: notOwner }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should remove token metadata when called by owner', async () => { it('should remove token metadata when called by owner', async () => {
@ -241,17 +240,17 @@ describe('TokenRegistry', () => {
it('should throw if token does not exist', async () => { it('should throw if token does not exist', async () => {
const index = new BigNumber(0); const index = new BigNumber(0);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.removeToken.sendTransactionAsync(nullToken.address, index, { from: owner }), tokenReg.removeToken.sendTransactionAsync(nullToken.address, index, { from: owner }),
).to.be.rejectedWith(constants.REVERT); );
}); });
it('should throw if token at given index does not match address', async () => { it('should throw if token at given index does not match address', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner); await tokenRegWrapper.addTokenAsync(token2, owner);
const incorrectIndex = new BigNumber(0); const incorrectIndex = new BigNumber(0);
return expect( return expectRevertOrAlwaysFailingTransactionAsync(
tokenReg.removeToken.sendTransactionAsync(token2.address, incorrectIndex, { from: owner }), tokenReg.removeToken.sendTransactionAsync(token2.address, incorrectIndex, { from: owner }),
).to.be.rejectedWith(constants.REVERT); );
}); });
}); });
}); });

View File

@ -1,12 +1,11 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import 'make-promises-safe'; import 'make-promises-safe';
import * as Web3 from 'web3';
import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_e_r_c20_token'; import { DummyERC20TokenContract } from '../src/generated_contract_wrappers/dummy_e_r_c20_token';
import { artifacts } from '../src/utils/artifacts'; import { artifacts } from '../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync, expectRevertOrOtherErrorAsync } from '../src/utils/assertions';
import { chaiSetup } from '../src/utils/chai_setup'; import { chaiSetup } from '../src/utils/chai_setup';
import { constants } from '../src/utils/constants'; import { constants } from '../src/utils/constants';
import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper'; import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper';
@ -55,8 +54,9 @@ describe('UnlimitedAllowanceToken', () => {
it('should throw if owner has insufficient balance', async () => { it('should throw if owner has insufficient balance', async () => {
const ownerBalance = await token.balanceOf.callAsync(owner); const ownerBalance = await token.balanceOf.callAsync(owner);
const amountToTransfer = ownerBalance.plus(1); const amountToTransfer = ownerBalance.plus(1);
return expect(token.transfer.callAsync(spender, amountToTransfer, { from: owner })).to.be.rejectedWith( return expectRevertOrOtherErrorAsync(
constants.REVERT, token.transfer.callAsync(spender, amountToTransfer, { from: owner }),
constants.ERC20_INSUFFICIENT_BALANCE,
); );
}); });
@ -93,11 +93,12 @@ describe('UnlimitedAllowanceToken', () => {
await token.approve.sendTransactionAsync(spender, amountToTransfer, { from: owner }), await token.approve.sendTransactionAsync(spender, amountToTransfer, { from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS, constants.AWAIT_TRANSACTION_MINED_MS,
); );
return expect( return expectRevertOrOtherErrorAsync(
token.transferFrom.callAsync(owner, spender, amountToTransfer, { token.transferFrom.callAsync(owner, spender, amountToTransfer, {
from: spender, from: spender,
}), }),
).to.be.rejectedWith(constants.REVERT); constants.ERC20_INSUFFICIENT_BALANCE,
);
}); });
it('should throw if spender has insufficient allowance', async () => { it('should throw if spender has insufficient allowance', async () => {
@ -108,11 +109,12 @@ describe('UnlimitedAllowanceToken', () => {
const isSpenderAllowanceInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; const isSpenderAllowanceInsufficient = spenderAllowance.cmp(amountToTransfer) < 0;
expect(isSpenderAllowanceInsufficient).to.be.true(); expect(isSpenderAllowanceInsufficient).to.be.true();
return expect( return expectRevertOrOtherErrorAsync(
token.transferFrom.callAsync(owner, spender, amountToTransfer, { token.transferFrom.callAsync(owner, spender, amountToTransfer, {
from: spender, from: spender,
}), }),
).to.be.rejectedWith(constants.REVERT); constants.ERC20_INSUFFICIENT_ALLOWANCE,
);
}); });
it('should return true on a 0 value transfer', async () => { it('should return true on a 0 value transfer', async () => {

View File

@ -1,9 +1,8 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import 'make-promises-safe'; import 'make-promises-safe';
import * as Web3 from 'web3';
import { ZRXTokenContract } from '../src/generated_contract_wrappers/zrx_token'; import { ZRXTokenContract } from '../src/generated_contract_wrappers/zrx_token';
import { artifacts } from '../src/utils/artifacts'; import { artifacts } from '../src/utils/artifacts';

View File

@ -1,4 +1,13 @@
[ [
{
"version": "0.4.3",
"changes": [
{
"note": "Add optional parameter shouldUseFakeGasEstimate to Web3Config",
"pr": 622
}
]
},
{ {
"version": "0.4.2", "version": "0.4.2",
"changes": [ "changes": [

View File

@ -1,5 +1,10 @@
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { uniqueVersionIds, Web3Wrapper } from '@0xproject/web3-wrapper';
import * as Web3 from 'web3'; import { includes } from 'lodash';
enum NodeType {
Geth = 'GETH',
Ganache = 'GANACHE',
}
export class BlockchainLifecycle { export class BlockchainLifecycle {
private _web3Wrapper: Web3Wrapper; private _web3Wrapper: Web3Wrapper;
@ -8,17 +13,47 @@ export class BlockchainLifecycle {
this._web3Wrapper = web3Wrapper; this._web3Wrapper = web3Wrapper;
this._snapshotIdsStack = []; this._snapshotIdsStack = [];
} }
// TODO: In order to run these tests on an actual node, we should check if we are running against
// TestRPC, if so, use snapshots, otherwise re-deploy contracts before every test
public async startAsync(): Promise<void> { public async startAsync(): Promise<void> {
const nodeType = await this._getNodeTypeAsync();
switch (nodeType) {
case NodeType.Ganache:
const snapshotId = await this._web3Wrapper.takeSnapshotAsync(); const snapshotId = await this._web3Wrapper.takeSnapshotAsync();
this._snapshotIdsStack.push(snapshotId); this._snapshotIdsStack.push(snapshotId);
break;
case NodeType.Geth:
const blockNumber = await this._web3Wrapper.getBlockNumberAsync();
this._snapshotIdsStack.push(blockNumber);
break;
default:
throw new Error(`Unknown node type: ${nodeType}`);
}
} }
public async revertAsync(): Promise<void> { public async revertAsync(): Promise<void> {
const nodeType = await this._getNodeTypeAsync();
switch (nodeType) {
case NodeType.Ganache:
const snapshotId = this._snapshotIdsStack.pop() as number; const snapshotId = this._snapshotIdsStack.pop() as number;
const didRevert = await this._web3Wrapper.revertSnapshotAsync(snapshotId); const didRevert = await this._web3Wrapper.revertSnapshotAsync(snapshotId);
if (!didRevert) { if (!didRevert) {
throw new Error(`Snapshot with id #${snapshotId} failed to revert`); throw new Error(`Snapshot with id #${snapshotId} failed to revert`);
} }
break;
case NodeType.Geth:
const blockNumber = this._snapshotIdsStack.pop() as number;
await this._web3Wrapper.setHeadAsync(blockNumber);
break;
default:
throw new Error(`Unknown node type: ${nodeType}`);
}
}
private async _getNodeTypeAsync(): Promise<NodeType> {
const version = await this._web3Wrapper.getNodeVersionAsync();
if (includes(version, uniqueVersionIds.geth)) {
return NodeType.Geth;
} else if (includes(version, uniqueVersionIds.ganache)) {
return NodeType.Ganache;
} else {
throw new Error(`Unknown client version: ${version}`);
}
} }
} }

View File

@ -7,10 +7,8 @@ import ProviderEngine = require('web3-provider-engine');
import RpcSubprovider = require('web3-provider-engine/subproviders/rpc'); import RpcSubprovider = require('web3-provider-engine/subproviders/rpc');
import { EmptyWalletSubprovider, FakeGasEstimateSubprovider, GanacheSubprovider } from '@0xproject/subproviders'; import { EmptyWalletSubprovider, FakeGasEstimateSubprovider, GanacheSubprovider } from '@0xproject/subproviders';
import { Provider } from 'ethereum-types';
import * as fs from 'fs'; import * as fs from 'fs';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as process from 'process';
import { constants } from './constants'; import { constants } from './constants';
import { env, EnvVars } from './env'; import { env, EnvVars } from './env';
@ -19,16 +17,22 @@ export interface Web3Config {
hasAddresses?: boolean; // default: true hasAddresses?: boolean; // default: true
shouldUseInProcessGanache?: boolean; // default: false shouldUseInProcessGanache?: boolean; // default: false
rpcUrl?: string; // default: localhost:8545 rpcUrl?: string; // default: localhost:8545
shouldUseFakeGasEstimate?: boolean; // default: true
} }
export const web3Factory = { export const web3Factory = {
getRpcProvider(config: Web3Config = {}): ProviderEngine { getRpcProvider(config: Web3Config = {}): ProviderEngine {
const provider = new ProviderEngine(); const provider = new ProviderEngine();
const hasAddresses = _.isUndefined(config.hasAddresses) || config.hasAddresses; const hasAddresses = _.isUndefined(config.hasAddresses) || config.hasAddresses;
config.shouldUseFakeGasEstimate =
_.isUndefined(config.shouldUseFakeGasEstimate) || config.shouldUseFakeGasEstimate;
if (!hasAddresses) { if (!hasAddresses) {
provider.addProvider(new EmptyWalletSubprovider()); provider.addProvider(new EmptyWalletSubprovider());
} }
if (config.shouldUseFakeGasEstimate) {
provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_LIMIT)); provider.addProvider(new FakeGasEstimateSubprovider(constants.GAS_LIMIT));
}
const logger = { const logger = {
log: (arg: any) => { log: (arg: any) => {
fs.appendFileSync('ganache.log', `${arg}\n`); fs.appendFileSync('ganache.log', `${arg}\n`);

View File

@ -1,6 +1,5 @@
import { Web3Wrapper } from '@0xproject/web3-wrapper'; import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import { BlockParamLiteral } from 'ethereum-types';
import 'make-promises-safe'; import 'make-promises-safe';
import 'mocha'; import 'mocha';
@ -18,6 +17,7 @@ describe('BlockchainLifecycle tests', () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
await web3Wrapper.mineBlockAsync(); await web3Wrapper.mineBlockAsync();
const blockNumberAfter = await web3Wrapper.getBlockNumberAsync(); const blockNumberAfter = await web3Wrapper.getBlockNumberAsync();
// tslint:disable-next-line:restrict-plus-operands
expect(blockNumberAfter).to.be.equal(blockNumberBefore + 1); expect(blockNumberAfter).to.be.equal(blockNumberBefore + 1);
await blockchainLifecycle.revertAsync(); await blockchainLifecycle.revertAsync();
const blockNumberAfterRevert = await web3Wrapper.getBlockNumberAsync(); const blockNumberAfterRevert = await web3Wrapper.getBlockNumberAsync();

View File

@ -16,6 +16,7 @@ describe('RPC tests', () => {
const blockNumberBefore = await web3Wrapper.getBlockNumberAsync(); const blockNumberBefore = await web3Wrapper.getBlockNumberAsync();
await web3Wrapper.mineBlockAsync(); await web3Wrapper.mineBlockAsync();
const blockNumberAfter = await web3Wrapper.getBlockNumberAsync(); const blockNumberAfter = await web3Wrapper.getBlockNumberAsync();
// tslint:disable-next-line:restrict-plus-operands
expect(blockNumberAfter).to.be.equal(blockNumberBefore + 1); expect(blockNumberAfter).to.be.equal(blockNumberBefore + 1);
}); });
}); });
@ -26,6 +27,7 @@ describe('RPC tests', () => {
await web3Wrapper.increaseTimeAsync(TIME_DELTA); await web3Wrapper.increaseTimeAsync(TIME_DELTA);
await web3Wrapper.mineBlockAsync(); await web3Wrapper.mineBlockAsync();
const blockTimestampAfter = await web3Wrapper.getBlockTimestampAsync(BlockParamLiteral.Latest); const blockTimestampAfter = await web3Wrapper.getBlockTimestampAsync(BlockParamLiteral.Latest);
// tslint:disable-next-line:restrict-plus-operands
expect(blockTimestampAfter).to.be.at.least(blockTimestampBefore + TIME_DELTA); expect(blockTimestampAfter).to.be.at.least(blockTimestampBefore + TIME_DELTA);
}); });
}); });

View File

@ -0,0 +1,25 @@
FROM alpine:3.7
RUN \
apk add --update go git make gcc musl-dev linux-headers ca-certificates && \
# TODO(albrow): Change the Git URL and branch once we have all relvant PRs
# merged to upstream.
git clone --depth 1 --branch '0x-testing' https://github.com/0xProject/go-ethereum && \
(cd go-ethereum && make geth) && \
cp go-ethereum/build/bin/geth /geth && \
apk del go git make gcc musl-dev linux-headers && \
rm -rf /go-ethereum && rm -rf /var/cache/apk/*
RUN mkdir ~/devnet
WORKDIR ~/devnet
COPY genesis.json .
COPY node0/ ./node0
COPY run.sh .
RUN /geth --datadir node0/ init genesis.json
EXPOSE 8501
EXPOSE 30310
ENTRYPOINT ./run.sh

110
packages/devnet/README.md Normal file
View File

@ -0,0 +1,110 @@
## 0x Devnet
A private, single-node PoA Ethereum network for testing purposes only. It uses
Geth and the PoA implementation called "Clique".
## Installation
The devnet requires Docker to run (the latest version is recommended).
In the package root directory, run:
```
docker build -t 0x-devnet .
```
## Usage
To start the network, run:
```
docker run -it --rm -p 8501:8501 0x-devnet
```
Depending on your OS and how you installed docker, you may need to prefix any
docker commands with `sudo`.
The Docker container exposes the JSON RPC API at port 8501, and this is the
primary way you are expected to interact with the devnet. The following
endpoints are supported: `personal,db,eth,net,web3,txpool,miner,debug`.
You can stop the network with `docker stop` and it will automatically clean up
after itself. (`docker stop` typically requires you to use `docker ps` to find
the name of the currently running container).
### Configuration
The devnet network only has a single node and uses PoA instead of PoW. That
means that one node, called the "sealer", is the ultimate authority for
validating transactions and adding new blocks to the chain. Since there is no
PoW it also means that mining does not require significant computational
resources. You can learn more about PoA and the Geth-specific implementation
called "Clique" in [EIP-225](https://github.com/ethereum/EIPs/issues/225).
The address of the "sealer" is `0xe8816898d851d5b61b7f950627d04d794c07ca37`. The
password associated with the account is "password" and the (encrypted) private
keys are visible in the **node0/keystore** directory. This account is already
"unlocked" in the Geth node by default, so you can do things like sign and send
transactions from this account using the JSON RPC endpoints directly.
There are also a number of other addresses that have hard-coded starting
balances for testing purposes. You can see the details in the **genesis.json**
file. All of these accounts are also unlocked by default.
### Additional JSON RPC Methods
In addition to the
[standard JSON RPC methods](https://github.com/ethereum/wiki/wiki/JSON-RPC) and
the
[Geth Management API](https://github.com/ethereum/go-ethereum/wiki/Management-APIs)
The devnet node supports some additional JSON RPC methods:
#### debug_increaseTime
Increases the timestamp of the next mined block.
##### Parameters
`Number` - The number of seconds by which to increase the time offset.
##### Returns
`Number` - The total number of seconds by which the time offset has been
increased (this includes all calls to `debug_increaseTime`).
##### Example
```js
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"debug_increaseTime","params":[100],"id":67}'
// Result
{
"id":67,
"jsonrpc": "2.0",
"result": "5000"
}
```
### Mining
The node will automatically (nearly instantly) mine a block whenever new
transactions are added to the transaction pool. If there are no transactions in
the pool, it will wait.
To stop mining, use the
[`miner.stop`](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#miner_stop)
method.
To start mining again, you can use the
[`miner.start`](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#miner_start)
JSON RPC method.
## Contributing
We strongly recommend that the community help us make improvements and determine
the future direction of the protocol. To report bugs within this package, please
create an issue in this repository.
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting
started.

View File

@ -0,0 +1,61 @@
{
"config": {
"chainId": 50,
"homesteadBlock": 1,
"eip150Block": 2,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip155Block": 3,
"eip158Block": 3,
"byzantiumBlock": 4,
"clique": {
"period": 0,
"epoch": 30000
}
},
"nonce": "0x0",
"timestamp": "0x5af1ffac",
"extraData":
"0x0000000000000000000000000000000000000000000000000000000000000000e8816898d851d5b61b7f950627d04d794c07ca370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x4c4b400000",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"0xe8816898d851d5b61b7f950627d04d794c07ca37": {
"balance": "0x56BC75E2D63100000"
},
"0x5409ed021d9299bf6814279a6a1411a7e866a631": {
"balance": "0x56BC75E2D63100000"
},
"0x6ecbe1db9ef729cbe972c83fb886247691fb6beb": {
"balance": "0x56BC75E2D63100000"
},
"0xe36ea790bc9d7ab70c55260c66d52b1eca985f84": {
"balance": "0x56BC75E2D63100000"
},
"0xe834ec434daba538cd1b9fe1582052b880bd7e63": {
"balance": "0x56BC75E2D63100000"
},
"0x78dc5d2d739606d31509c31d654056a45185ecb6": {
"balance": "0x56BC75E2D63100000"
},
"0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872": {
"balance": "0x56BC75E2D63100000"
},
"0x06cef8e666768cc40cc78cf93d9611019ddcb628": {
"balance": "0x56BC75E2D63100000"
},
"0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d": {
"balance": "0x56BC75E2D63100000"
},
"0x7457d5e02197480db681d3fdf256c7aca21bdc12": {
"balance": "0x56BC75E2D63100000"
},
"0x91c987bf62d25945db517bdaa840a6c661374402": {
"balance": "0x56BC75E2D63100000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}

View File

@ -0,0 +1 @@
{"address":"5409ed021d9299bf6814279a6a1411a7e866a631","crypto":{"cipher":"aes-128-ctr","ciphertext":"7c7bdd62b303eb3a42d5d8e935825ed5a05a47cb2cef71e346c61b1bd582f1aa","cipherparams":{"iv":"7fd6c9d9f9893f2c480735b5386b6d75"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"79cc86edc3a668845a68fabb3913710b7504922e47aac8513ab3d6a28d090218"},"mac":"8a593ae0d0b964e47625bc964b6d389f5687f5bde631b4913136db4ab1b8083e"},"id":"29f637ba-6a65-4401-a0d1-30e1554bd776","version":3}

View File

@ -0,0 +1 @@
{"address":"6ecbe1db9ef729cbe972c83fb886247691fb6beb","crypto":{"cipher":"aes-128-ctr","ciphertext":"ecaf4f2839d74d92e2cb87c2fc7d52862661b46e697d70acfbe43f0893db73ed","cipherparams":{"iv":"7641c3a107228f8a901c07a07ea1f70d"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c67c9fb30648df6985c0490b6603382147e7dc1ea28ca8c934af4a453ec0555b"},"mac":"985dca9ce65ad400fa4c9009742be2d409f402fe05203fc1278cfd1451729e8d"},"id":"e8634edc-08e6-415e-8d65-7985c4c4a05c","version":3}

View File

@ -0,0 +1 @@
{"address":"e36ea790bc9d7ab70c55260c66d52b1eca985f84","crypto":{"cipher":"aes-128-ctr","ciphertext":"49f89d7d612049f5f3581fc7c97d32ec9c9a2ca3c11165587139f16bfb29de6b","cipherparams":{"iv":"9767e0687a097c5b57e9cb30eec9bc0a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"3e8f23332df99d519b602a0f6f4724338ba3fd9e7e313c337a92ffd1cafa19f1"},"mac":"4892051a669d45bb7de32a5eab63ee8fe52485a02218ce1806515da2adbd6584"},"id":"3488ad36-4a9d-4282-8651-7939b822429d","version":3}

View File

@ -0,0 +1 @@
{"address":"e834ec434daba538cd1b9fe1582052b880bd7e63","crypto":{"cipher":"aes-128-ctr","ciphertext":"a8ae3896739c63fc3bfe034277f6a1924a1c0ddc3f6747391dada8e61e15a928","cipherparams":{"iv":"f4f4d786cd3650a428a8bac5a6c824b1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"9acecc321bcab9b69ffdea494b8894ad0221c30f05c17d2302e315db8708ecc6"},"mac":"fc416b8f539fdc1e39e87a3bd2a69b04455875de701ced60cc8948b222171380"},"id":"0d9703e8-14fc-45d0-a425-2c40b8ae846a","version":3}

View File

@ -0,0 +1 @@
{"address":"78dc5d2d739606d31509c31d654056a45185ecb6","crypto":{"cipher":"aes-128-ctr","ciphertext":"25e90e593f08e9e3adc426c8685d90db5d1c04957e9dc8d5fab4ae30c3306b61","cipherparams":{"iv":"72ece22297a27363e795b678bcbd6be5"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"2201502b9d3c4e2076d9d15bfd9da3a6c75d9e2e574aabb29c3bc5a3b5ec55a5"},"mac":"13d709ed4bd2f5bf4973fc1373f8434835f0d12dc99b32c6fc14d9df7f41c62d"},"id":"3902dff4-5681-4646-b825-849f96efeec5","version":3}

View File

@ -0,0 +1 @@
{"address":"a8dda8d7f5310e4a9e24f8eba77e091ac264f872","crypto":{"cipher":"aes-128-ctr","ciphertext":"0d67c13cf0b130e8ffa1aaca5df372f727164e633f8e0e28a3e54d0884ffb568","cipherparams":{"iv":"619cd539cda9f40abb45bba00b5fe53d"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"4effcd9b6fe71ee31cfe9057290154329b9af3acb6dcc46be7f78b5b9dcd3f42"},"mac":"c6eecd25944f4250b7b875d76bfbb60cc4e8db1d081621d1a2ddb72ea4e52a6d"},"id":"556bd3f1-1e5b-47a4-9b6e-448b9989d7d3","version":3}

View File

@ -0,0 +1 @@
{"address":"06cef8e666768cc40cc78cf93d9611019ddcb628","crypto":{"cipher":"aes-128-ctr","ciphertext":"38c9ca150932dc8c5ec5c65796425b2de98295cae64db08b816da2c06fc52c20","cipherparams":{"iv":"512127e8e606c481612473e7bc4d38f1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"16c4cabfd13cae2df66d8ff9acc7f503c95c808b00d0bb6a12932203889c679b"},"mac":"52297b496e8751627dea1ee17bf5cbea1926f90bcde3ffc8baa089184672f875"},"id":"31102097-86e4-4e19-ad73-03c3de67bf3b","version":3}

View File

@ -0,0 +1 @@
{"address":"4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d","crypto":{"cipher":"aes-128-ctr","ciphertext":"ca7aedbacc960fc0fcb418606d7bdf042c36cc2808a5c94ac222cc0b44a9970d","cipherparams":{"iv":"3b1fe5da1cf5d6cd2ceaaf24c008c897"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"a94e4d41d77ff6dc54beda30c7a46d8f3cc312ebeffa0352d679f7e3fc5301dc"},"mac":"9a82bf60103d05878f8af3c07765c22cba3df9b1c4376eaf859e47b805666e42"},"id":"ab68c67b-e15a-4ade-b3d9-2180a32b28fe","version":3}

View File

@ -0,0 +1 @@
{"address":"7457d5e02197480db681d3fdf256c7aca21bdc12","crypto":{"cipher":"aes-128-ctr","ciphertext":"720dcc2889c7b3636f9f659650181b0d46d82420460e23454277273f528baaee","cipherparams":{"iv":"1510028e2b9988d1a73b71cbb692d085"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"5db2b62f4d1f55a3f24c014c4f23f3ec9a2992dca6c2a89c24a566f99a079396"},"mac":"22c6fb134fd0a748195ea83e9ccb490ab2c9a3e8761f9d74ea6d02abbdeb8a43"},"id":"704c31f8-8ca2-4b49-9fdc-5923f5712dad","version":3}

View File

@ -0,0 +1 @@
{"address":"91c987bf62d25945db517bdaa840a6c661374402","crypto":{"cipher":"aes-128-ctr","ciphertext":"8f461f3c74643f382f7fc1f71719d5a89ed8cf75854d8a1b53e133997b53a386","cipherparams":{"iv":"cf595fb7680d36b4f5a01599ee54d2d1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"73a9e599369d2bfaedd044559415147240c3517f6cd1dec8f77a98993d1ceaf8"},"mac":"c8be4dc59ad28d40f7b549a6b72834d149c84d67dc35e687676bbee0e07be395"},"id":"21cca6fb-7876-4e39-a986-a0a37f90da6d","version":3}

View File

@ -0,0 +1 @@
{"address":"e8816898d851d5b61b7f950627d04d794c07ca37","crypto":{"cipher":"aes-128-ctr","ciphertext":"1ff4add6955cba7ddaf29f66d7d21c5e1d714ef6191fbc651ae60f2ea3c95e8f","cipherparams":{"iv":"3ff869fbdbe1a523cdb327780365976e"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"7372dbae5fb318f8684902e099c311d4188721d677974d729711762c7ef6030c"},"mac":"485fa5dc701067782baa1589716a53110c7f917eb259e35ebca7265bbb7150b1"},"id":"89edb004-5b00-4607-a3af-a0d9ab9b1c34","version":3}

View File

@ -0,0 +1,11 @@
password
password
password
password
password
password
password
password
password
password
password

42
packages/devnet/run.sh Executable file
View File

@ -0,0 +1,42 @@
set -e
# Create log directory for Geth
mkdir -p /var/log
# Start Geth in background and redirect output to log file
/geth \
--verbosity 5 \
--datadir node0/ \
--syncmode 'full' \
--nat none \
--nodiscover \
--port 30310 \
--txpool.journal '' \
--rpc \
--rpcaddr '0.0.0.0' \
--rpcport 8501 \
--rpcapi 'personal,db,eth,net,web3,txpool,miner,debug' \
--networkid 50 \
--gasprice '2000000000' \
--targetgaslimit '0x4c4b400000' \
--mine \
--etherbase '0xe8816898d851d5b61b7f950627d04d794c07ca37' \
--unlock '0xe8816898d851d5b61b7f950627d04d794c07ca37,0x5409ed021d9299bf6814279a6a1411a7e866a631,0x6ecbe1db9ef729cbe972c83fb886247691fb6beb,0xe36ea790bc9d7ab70c55260c66d52b1eca985f84,0xe834ec434daba538cd1b9fe1582052b880bd7e63,0x78dc5d2d739606d31509c31d654056a45185ecb6,0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872,0x06cef8e666768cc40cc78cf93d9611019ddcb628,0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d,0x7457d5e02197480db681d3fdf256c7aca21bdc12,0x91c987bf62d25945db517bdaa840a6c661374402' \
--password=node0/password.txt \
> /var/log/geth &
# Wait for Geth to unlock the first account
sleep 10
# Send some transactions.
# HACK(albrow): 🐉 We have to do this so that debug.setHead works correctly.
# (Geth does not seem to like debug.setHead(0), so by sending some transactions
# we increase the current block number beyond 0). Additionally, some tests seem
# to break when there are fewer than 3 blocks in the chain. (We have no idea
# why, but it was consistently reproducible).
/geth --datadir node0/ attach --exec 'eth.sendTransaction({"from": "0x5409ED021D9299bf6814279A6A1411A7e866A631", "to": "0x84bd1cfa409cb0bb9b23b8b1a33515b4ac00a0af", "value": "0x1"})'
/geth --datadir node0/ attach --exec 'eth.sendTransaction({"from": "0x5409ED021D9299bf6814279A6A1411A7e866A631", "to": "0x84bd1cfa409cb0bb9b23b8b1a33515b4ac00a0af", "value": "0x1"})'
/geth --datadir node0/ attach --exec 'eth.sendTransaction({"from": "0x5409ED021D9299bf6814279A6A1411A7e866A631", "to": "0x84bd1cfa409cb0bb9b23b8b1a33515b4ac00a0af", "value": "0x1"})'
# Use tail to re-attach to the log file and actually see the output.
tail -f /var/log/geth

View File

@ -12,7 +12,18 @@
"build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts", "build": "tsc && copyfiles -u 2 './lib/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib scripts", "clean": "shx rm -rf lib scripts",
"lint": "tslint --project .", "lint": "tslint --project .",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js" "manual:postpublish": "yarn build; node ./scripts/postpublish.js",
"docs:stage": "node scripts/stage_docs.js",
"docs:json": "typedoc --excludePrivate --excludeExternals --target ES5 --json $JSON_FILE_PATH $PROJECT_FILES",
"upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json"
},
"config": {
"postpublish": {
"docPublishConfigs": {
"s3BucketPath": "s3://doc-jsons/ethereum-types/",
"s3StagingBucketPath": "s3://staging-doc-jsons/ethereum-types/"
}
}
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {

View File

@ -0,0 +1,8 @@
import { postpublishUtils } from '@0xproject/monorepo-scripts';
import * as packageJSON from '../package.json';
import * as tsConfigJSON from '../tsconfig.json';
const cwd = `${__dirname}/..`;
// tslint:disable-next-line:no-floating-promises
postpublishUtils.publishDocsToStagingAsync(packageJSON, tsConfigJSON, cwd);

View File

@ -9,10 +9,10 @@
"build": "yarn pre_build && tsc", "build": "yarn pre_build && tsc",
"pre_build": "run-s update_artifacts generate_contract_wrappers", "pre_build": "run-s update_artifacts generate_contract_wrappers",
"update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json lib/artifacts; done;", "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json lib/artifacts; done;",
"generate_contract_wrappers": "abi-gen --abis 'lib/artifacts/@(Exchange|ERC20Token|DummyERC20Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'", "generate_contract_wrappers": "abi-gen --abis 'lib/artifacts/@(Exchange|ERC20Token|DummyERC20Token).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers",
"copy_monorepo_scripts": "copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", "copy_monorepo_scripts": "copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts",
"clean": "shx rm -rf lib scripts src/generated_contract_wrappers", "clean": "shx rm -rf lib scripts src/generated_contract_wrappers",
"lint": "tslint --project .", "lint": "tslint --project . --exclude **/src/generated_contract_wrappers/**/*",
"manual:postpublish": "yarn build; node ./scripts/postpublish.js" "manual:postpublish": "yarn build; node ./scripts/postpublish.js"
}, },
"config": { "config": {

View File

@ -7,17 +7,18 @@
"private": true, "private": true,
"description": "Example solidity project using 0x dev tools", "description": "Example solidity project using 0x dev tools",
"scripts": { "scripts": {
"watch": "tsc -w",
"lint": "tslint --project . --exclude **/src/contract_wrappers/**/*",
"watch_without_deps": "yarn pre_build && tsc -w", "watch_without_deps": "yarn pre_build && tsc -w",
"build": "yarn pre_build && tsc", "build": "yarn pre_build && tsc",
"pre_build": "run-s compile generate_contract_wrappers copy_artifacts", "pre_build": "run-s compile generate_contract_wrappers copy_artifacts",
"lint": "tslint --project .",
"clean": "shx rm -rf lib artifacts src/contract_wrappers", "clean": "shx rm -rf lib artifacts src/contract_wrappers",
"copy_artifacts": "copyfiles './artifacts/**/*' './contracts/**/*' ./lib", "copy_artifacts": "copyfiles './artifacts/**/*' './contracts/**/*' ./lib",
"test": "yarn run_mocha", "test": "yarn run_mocha",
"rebuild_and_test": "run-s build test", "rebuild_and_test": "run-s build test",
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --bail --exit", "run_mocha": "mocha lib/test/**/*_test.js lib/test/global_hooks.js --bail --exit",
"generate_contract_wrappers": "abi-gen --abis 'artifacts/Metacoin.json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers --backend ethers && prettier --write 'src/contract_wrappers/**.ts'", "generate_contract_wrappers": "abi-gen --abis 'artifacts/Metacoin.json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/contract_wrappers --backend ethers",
"coverage:report:text": "istanbul report text", "coverage:report:text": "istanbul report text",
"coverage:report:html": "istanbul report html && open coverage/index.html", "coverage:report:html": "istanbul report html && open coverage/index.html",
"coverage:report:lcov": "istanbul report lcov", "coverage:report:lcov": "istanbul report lcov",

View File

@ -1,7 +1,6 @@
import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils'; import { BlockchainLifecycle, devConstants } from '@0xproject/dev-utils';
import { ContractArtifact } from '@0xproject/sol-compiler'; import { ContractArtifact } from '@0xproject/sol-compiler';
import { BigNumber } from '@0xproject/utils'; import { BigNumber } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types'; import { LogWithDecodedArgs } from 'ethereum-types';
import 'make-promises-safe'; import 'make-promises-safe';
@ -18,7 +17,7 @@ const artifact: ContractArtifact = MetacoinArtifact as any;
chaiSetup.configure(); chaiSetup.configure();
const { expect } = chai; const { expect } = chai;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
// tslint:disable:no-unnecessary-type-assertion
describe('Metacoin', () => { describe('Metacoin', () => {
let metacoin: MetacoinContract; let metacoin: MetacoinContract;
const ownerAddress = devConstants.TESTRPC_FIRST_ADDRESS; const ownerAddress = devConstants.TESTRPC_FIRST_ADDRESS;
@ -116,3 +115,4 @@ describe('Metacoin', () => {
}); });
}); });
}); });
// tslint:enable:no-unnecessary-type-assertion

View File

@ -1,5 +1,4 @@
import { devConstants } from '@0xproject/dev-utils'; import { devConstants } from '@0xproject/dev-utils';
import * as path from 'path';
export const config = { export const config = {
networkId: 50, networkId: 50,

Some files were not shown because too many files have changed in this diff Show More