Merge pull request #368 from 0xProject/feature/abigen/addNetworkId

Add CLI option for networkId, add abi-gen to contracts package
This commit is contained in:
Leonid 2018-02-07 11:40:06 +01:00 committed by GitHub
commit 12d62e1157
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
80 changed files with 568 additions and 389 deletions

View File

@ -1,7 +1,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.js/tree/development/packages/abi-gen-templates. * Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/0x.js/contract_templates.
*/ */
// tslint:disable:no-consecutive-blank-lines
// tslint:disable-next-line:no-unused-variable // tslint:disable-next-line:no-unused-variable
import { TxData, TxDataPayable } from '@0xproject/types'; import { TxData, TxDataPayable } from '@0xproject/types';
import { BigNumber, classUtils, promisify } from '@0xproject/utils'; import { BigNumber, classUtils, promisify } from '@0xproject/utils';
@ -9,6 +10,24 @@ import * as Web3 from 'web3';
import {BaseContract} from './base_contract'; import {BaseContract} from './base_contract';
{{#if events}}
export type {{contractName}}ContractEventArgs =
{{#each events}}
| {{name}}ContractEventArgs{{#if @last}};{{/if}}
{{/each}}
export enum {{contractName}}Events {
{{#each events}}
{{name}} = '{{name}}',
{{/each}}
}
{{#each events}}
{{> event}}
{{/each}}
{{/if}}
export class {{contractName}}Contract extends BaseContract { export class {{contractName}}Contract extends BaseContract {
{{#each methods}} {{#each methods}}
{{#this.constant}} {{#this.constant}}

View File

@ -0,0 +1,5 @@
export interface {{name}}ContractEventArgs {
{{#each inputs}}
{{name}}: {{#returnType type}}{{/returnType}};
{{/each}}
}

View File

@ -5,19 +5,11 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { artifacts } from '../artifacts'; import { artifacts } from '../artifacts';
import { import { BlockRange, EventCallback, IndexedFilterValues, TransactionOpts, ZeroExError } from '../types';
BlockRange,
EtherTokenContractEventArgs,
EtherTokenEvents,
EventCallback,
IndexedFilterValues,
TransactionOpts,
ZeroExError,
} from '../types';
import { assert } from '../utils/assert'; import { assert } from '../utils/assert';
import { ContractWrapper } from './contract_wrapper'; import { ContractWrapper } from './contract_wrapper';
import { EtherTokenContract } from './generated/ether_token'; import { EtherTokenContract, EtherTokenContractEventArgs, EtherTokenEvents } from './generated/ether_token';
import { TokenWrapper } from './token_wrapper'; import { TokenWrapper } from './token_wrapper';
/** /**

View File

@ -12,10 +12,7 @@ import {
EventCallback, EventCallback,
ExchangeContractErrCodes, ExchangeContractErrCodes,
ExchangeContractErrs, ExchangeContractErrs,
ExchangeContractEventArgs,
ExchangeEvents,
IndexedFilterValues, IndexedFilterValues,
LogErrorContractEventArgs,
MethodOpts, MethodOpts,
Order, Order,
OrderAddresses, OrderAddresses,
@ -33,7 +30,12 @@ import { OrderValidationUtils } from '../utils/order_validation_utils';
import { utils } from '../utils/utils'; import { utils } from '../utils/utils';
import { ContractWrapper } from './contract_wrapper'; import { ContractWrapper } from './contract_wrapper';
import { ExchangeContract } from './generated/exchange'; import {
ExchangeContract,
ExchangeContractEventArgs,
ExchangeEvents,
LogErrorContractEventArgs,
} from './generated/exchange';
import { TokenWrapper } from './token_wrapper'; import { TokenWrapper } from './token_wrapper';
const SHOULD_VALIDATE_BY_DEFAULT = true; const SHOULD_VALIDATE_BY_DEFAULT = true;

View File

@ -5,21 +5,12 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { artifacts } from '../artifacts'; import { artifacts } from '../artifacts';
import { import { BlockRange, EventCallback, IndexedFilterValues, MethodOpts, TransactionOpts, ZeroExError } from '../types';
BlockRange,
EventCallback,
IndexedFilterValues,
MethodOpts,
TokenContractEventArgs,
TokenEvents,
TransactionOpts,
ZeroExError,
} from '../types';
import { assert } from '../utils/assert'; import { assert } from '../utils/assert';
import { constants } from '../utils/constants'; import { constants } from '../utils/constants';
import { ContractWrapper } from './contract_wrapper'; import { ContractWrapper } from './contract_wrapper';
import { TokenContract } from './generated/token'; import { TokenContract, TokenContractEventArgs, TokenEvents } from './generated/token';
import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper'; import { TokenTransferProxyWrapper } from './token_transfer_proxy_wrapper';
/** /**

View File

@ -9,26 +9,13 @@ export {
ExchangeContractErrs, ExchangeContractErrs,
ContractEvent, ContractEvent,
Token, Token,
ExchangeEvents,
TokenEvents,
IndexedFilterValues, IndexedFilterValues,
BlockRange, BlockRange,
OrderCancellationRequest, OrderCancellationRequest,
OrderFillRequest, OrderFillRequest,
LogErrorContractEventArgs,
LogCancelContractEventArgs,
LogFillContractEventArgs,
ExchangeContractEventArgs,
TransferContractEventArgs,
ApprovalContractEventArgs,
TokenContractEventArgs,
EtherTokenContractEventArgs,
WithdrawalContractEventArgs,
DepositContractEventArgs,
ContractEventArgs, ContractEventArgs,
Web3Provider, Web3Provider,
ZeroExConfig, ZeroExConfig,
EtherTokenEvents,
MethodOpts, MethodOpts,
OrderTransactionOpts, OrderTransactionOpts,
TransactionOpts, TransactionOpts,
@ -50,4 +37,26 @@ export {
TransactionReceiptWithDecodedLogs, TransactionReceiptWithDecodedLogs,
} from '@0xproject/types'; } from '@0xproject/types';
export {
EtherTokenContractEventArgs,
WithdrawalContractEventArgs,
DepositContractEventArgs,
EtherTokenEvents,
} from './contract_wrappers/generated/ether_token';
export {
TransferContractEventArgs,
ApprovalContractEventArgs,
TokenContractEventArgs,
TokenEvents,
} from './contract_wrappers/generated/token';
export {
LogErrorContractEventArgs,
LogCancelContractEventArgs,
LogFillContractEventArgs,
ExchangeContractEventArgs,
ExchangeEvents,
} from './contract_wrappers/generated/exchange';
export { TransactionReceipt } from '@0xproject/types'; export { TransactionReceipt } from '@0xproject/types';

View File

@ -6,26 +6,32 @@ import * as _ from 'lodash';
import { ZeroEx } from '../0x'; import { ZeroEx } from '../0x';
import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper'; import { ExchangeWrapper } from '../contract_wrappers/exchange_wrapper';
import {
DepositContractEventArgs,
EtherTokenEvents,
WithdrawalContractEventArgs,
} from '../contract_wrappers/generated/ether_token';
import {
ExchangeEvents,
LogCancelContractEventArgs,
LogFillContractEventArgs,
} from '../contract_wrappers/generated/exchange';
import {
ApprovalContractEventArgs,
TokenEvents,
TransferContractEventArgs,
} from '../contract_wrappers/generated/token';
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';
import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store'; import { OrderFilledCancelledLazyStore } from '../stores/order_filled_cancelled_lazy_store';
import { import {
ApprovalContractEventArgs,
ContractEventArgs, ContractEventArgs,
DepositContractEventArgs,
EtherTokenEvents,
ExchangeContractErrs, ExchangeContractErrs,
ExchangeEvents,
LogCancelContractEventArgs,
LogEvent, LogEvent,
LogFillContractEventArgs,
OnOrderStateChangeCallback, OnOrderStateChangeCallback,
OrderState, OrderState,
OrderStateWatcherConfig, OrderStateWatcherConfig,
SignedOrder, SignedOrder,
TokenEvents,
TransferContractEventArgs,
WithdrawalContractEventArgs,
ZeroExError, ZeroExError,
} from '../types'; } from '../types';
import { assert } from '../utils/assert'; import { assert } from '../utils/assert';

View File

@ -4,6 +4,10 @@ import { BlockParam, BlockParamLiteral, ContractEventArg, LogWithDecodedArgs } f
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { EtherTokenContractEventArgs, EtherTokenEvents } from './contract_wrappers/generated/ether_token';
import { ExchangeContractEventArgs, ExchangeEvents } from './contract_wrappers/generated/exchange';
import { TokenContractEventArgs, TokenEvents } from './contract_wrappers/generated/token';
export enum ZeroExError { export enum ZeroExError {
ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST', ExchangeContractDoesNotExist = 'EXCHANGE_CONTRACT_DOES_NOT_EXIST',
ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST', ZRXContractDoesNotExist = 'ZRX_CONTRACT_DOES_NOT_EXIST',
@ -101,60 +105,6 @@ export interface ContractEvent {
args: ContractEventArgs; args: ContractEventArgs;
} }
export interface LogFillContractEventArgs {
maker: string;
taker: string;
feeRecipient: string;
makerToken: string;
takerToken: string;
filledMakerTokenAmount: BigNumber;
filledTakerTokenAmount: BigNumber;
paidMakerFee: BigNumber;
paidTakerFee: BigNumber;
tokens: string;
orderHash: string;
}
export interface LogCancelContractEventArgs {
maker: string;
feeRecipient: string;
makerToken: string;
takerToken: string;
cancelledMakerTokenAmount: BigNumber;
cancelledTakerTokenAmount: BigNumber;
tokens: string;
orderHash: string;
}
export interface LogErrorContractEventArgs {
errorId: BigNumber;
orderHash: string;
}
export type ExchangeContractEventArgs =
| LogFillContractEventArgs
| LogCancelContractEventArgs
| LogErrorContractEventArgs;
export interface TransferContractEventArgs {
_from: string;
_to: string;
_value: BigNumber;
}
export interface ApprovalContractEventArgs {
_owner: string;
_spender: string;
_value: BigNumber;
}
export interface DepositContractEventArgs {
_owner: string;
_value: BigNumber;
}
export interface WithdrawalContractEventArgs {
_owner: string;
_value: BigNumber;
}
export type TokenContractEventArgs = TransferContractEventArgs | ApprovalContractEventArgs;
export type EtherTokenContractEventArgs =
| TokenContractEventArgs
| DepositContractEventArgs
| WithdrawalContractEventArgs;
export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs; export type ContractEventArgs = ExchangeContractEventArgs | TokenContractEventArgs | EtherTokenContractEventArgs;
export interface Order { export interface Order {
@ -197,24 +147,6 @@ export interface TokenAddressBySymbol {
[symbol: string]: string; [symbol: string]: string;
} }
export enum ExchangeEvents {
LogFill = 'LogFill',
LogCancel = 'LogCancel',
LogError = 'LogError',
}
export enum TokenEvents {
Transfer = 'Transfer',
Approval = 'Approval',
}
export enum EtherTokenEvents {
Transfer = 'Transfer',
Approval = 'Approval',
Deposit = 'Deposit',
Withdrawal = 'Withdrawal',
}
export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents; export type ContractEvents = TokenEvents | ExchangeEvents | EtherTokenEvents;
export interface IndexedFilterValues { export interface IndexedFilterValues {

View File

@ -3,6 +3,7 @@
## v0.2.0 - _???_ ## v0.2.0 - _???_
* Added CLI options for explicit specifying location of partials and main template (#346) * Added CLI options for explicit specifying location of partials and main template (#346)
* Added CLI option to specify networkId, adding support for the JSON artifact format found in @0xproject/contracts
## v0.1.0 - _January 11, 2018_ ## v0.1.0 - _January 11, 2018_

View File

@ -17,6 +17,7 @@ import { utils } from './utils';
const ABI_TYPE_CONSTRUCTOR = 'constructor'; const ABI_TYPE_CONSTRUCTOR = 'constructor';
const ABI_TYPE_METHOD = 'function'; const ABI_TYPE_METHOD = 'function';
const ABI_TYPE_EVENT = 'event'; const ABI_TYPE_EVENT = 'event';
const DEFAULT_NETWORK_ID = 50;
const args = yargs const args = yargs
.option('abis', { .option('abis', {
@ -42,6 +43,11 @@ const args = yargs
demandOption: true, demandOption: true,
normalize: true, normalize: true,
}) })
.option('network-id', {
describe: 'ID of the network where contract ABIs are nested in artifacts',
type: 'number',
default: DEFAULT_NETWORK_ID,
})
.example( .example(
"$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'", "$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'",
'Full usage example', 'Full usage example',
@ -58,7 +64,10 @@ function registerPartials(partialsGlob: string) {
} }
function writeOutputFile(name: string, renderedTsCode: string): void { function writeOutputFile(name: string, renderedTsCode: string): void {
const fileName = toSnakeCase(name); let fileName = toSnakeCase(name);
if (fileName === 'z_r_x_token') {
fileName = 'zrx_token';
}
const filePath = `${args.output}/${fileName}.ts`; const filePath = `${args.output}/${fileName}.ts`;
fs.writeFileSync(filePath, renderedTsCode); fs.writeFileSync(filePath, renderedTsCode);
utils.log(`Created: ${chalk.bold(filePath)}`); utils.log(`Created: ${chalk.bold(filePath)}`);
@ -87,12 +96,19 @@ for (const abiFileName of abiFileNames) {
const namedContent = utils.getNamedContent(abiFileName); const namedContent = utils.getNamedContent(abiFileName);
utils.log(`Processing: ${chalk.bold(namedContent.name)}...`); utils.log(`Processing: ${chalk.bold(namedContent.name)}...`);
const parsedContent = JSON.parse(namedContent.content); const parsedContent = JSON.parse(namedContent.content);
const ABI = _.isArray(parsedContent) let ABI;
? parsedContent // ABI file if (_.isArray(parsedContent)) {
: parsedContent.abi; // Truffle contracts file ABI = parsedContent; // ABI file
} else if (!_.isUndefined(parsedContent.abi)) {
ABI = parsedContent.abi; // Truffle artifact
} else if (!_.isUndefined(parsedContent.networks) && !_.isUndefined(parsedContent.networks[args.networkId])) {
ABI = parsedContent.networks[args.networkId].abi; // 0x contracts package artifact
}
if (_.isUndefined(ABI)) { if (_.isUndefined(ABI)) {
utils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`); utils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`);
utils.log(`Please make sure your ABI file is either an array with ABI entries or an object with the abi key`); utils.log(
`Please make sure your ABI file is either an array with ABI entries or a truffle artifact or 0x deployer artifact`,
);
process.exit(1); process.exit(1);
} }
@ -103,10 +119,10 @@ for (const abiFileName of abiFileNames) {
const methodAbis = ABI.filter((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_METHOD) as Web3.MethodAbi[]; const methodAbis = ABI.filter((abi: Web3.AbiDefinition) => abi.type === ABI_TYPE_METHOD) as Web3.MethodAbi[];
const methodsData = _.map(methodAbis, methodAbi => { const methodsData = _.map(methodAbis, methodAbi => {
_.map(methodAbi.inputs, input => { _.map(methodAbi.inputs, (input, i: number) => {
if (_.isEmpty(input.name)) { if (_.isEmpty(input.name)) {
// Auto-generated getters don't have parameter names // Auto-generated getters don't have parameter names
input.name = 'index'; input.name = `index_${i}`;
} }
}); });
// This will make templates simpler // This will make templates simpler

View File

@ -0,0 +1,26 @@
/**
* This file is auto-generated using abi-gen. Don't edit directly.
* Templates can be found at https://github.com/0xProject/0x.js/tree/development/packages/abi-gen-templates.
*/
// tslint:disable:async-suffix member-ordering no-consecutive-blank-lines
// tslint:disable-next-line:no-unused-variable
import { TxData, TxDataPayable } from '@0xproject/types';
import { BigNumber, classUtils, promisify } from '@0xproject/utils';
import * as Web3 from 'web3';
import {BaseContract} from './base_contract';
export class {{contractName}}Contract extends BaseContract {
{{#each methods}}
{{#this.constant}}
{{> call contractName=../contractName}}
{{/this.constant}}
{{^this.constant}}
{{> tx contractName=../contractName}}
{{/this.constant}}
{{/each}}
constructor(web3ContractInstance: Web3.ContractInstance, defaults?: Partial<TxData>) {
super(web3ContractInstance, defaults);
classUtils.bindAll(this, ['_web3ContractInstance', '_defaults']);
}
} // tslint:disable:max-file-line-count

View File

@ -0,0 +1,10 @@
public async {{this.name}}(
{{> typed_params inputs=inputs}}
defaultBlock?: Web3.BlockParam,
): Promise<{{> return_type outputs=outputs}}> {
const self = this as {{contractName}}Contract;
const result = await self._web3ContractInstance.{{this.name}}.call(
{{> params inputs=inputs}}
);
return result;
}

View File

@ -0,0 +1,3 @@
{{#each inputs}}
{{name}},
{{/each}}

View File

@ -0,0 +1,10 @@
{{#if outputs.length}}
{{#singleReturnValue}}
{{#returnType outputs.0.type}}{{/returnType}}
{{/singleReturnValue}}
{{^singleReturnValue}}
[{{#each outputs}}{{#returnType type}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
{{/singleReturnValue}}
{{else}}
void
{{/if}}

View File

@ -0,0 +1,36 @@
public {{this.name}} = {
async sendTransactionAsync(
{{> typed_params inputs=inputs}}
{{#this.payable}}
txData: TxDataPayable = {},
{{/this.payable}}
{{^this.payable}}
txData: TxData = {},
{{/this.payable}}
): Promise<string> {
const self = this as {{contractName}}Contract;
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(txData);
const txHash = await self._web3ContractInstance.{{this.name}}(
{{> params inputs=inputs}}
txDataWithDefaults,
);
return txHash;
},
async callAsync(
{{> typed_params inputs=inputs}}
{{#this.payable}}
txData: TxDataPayable = {},
{{/this.payable}}
{{^this.payable}}
txData: TxData = {},
{{/this.payable}}
): Promise<{{> return_type outputs=outputs}}> {
const self = this as {{contractName}}Contract;
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(txData);
const returnValue = await self._web3ContractInstance.{{this.name}}.call(
{{> params inputs=inputs}}
txDataWithDefaults,
);
return returnValue;
},
};

View File

@ -0,0 +1,3 @@
{{#each inputs}}
{{name}}: {{#parameterType type}}{{/parameterType}},
{{/each}}

View File

@ -9,14 +9,15 @@
}, },
"scripts": { "scripts": {
"build:watch": "tsc -w", "build:watch": "tsc -w",
"prebuild": "run-s clean copy_artifacts", "prebuild": "run-s clean copy_artifacts generate_contract_wrappers",
"copy_artifacts": "copyfiles './artifacts/**/*' ./lib", "copy_artifacts": "copyfiles './src/artifacts/**/*' ./lib",
"build": "tsc", "build": "tsc",
"test": "run-s compile build run_mocha", "test": "run-s compile build run_mocha",
"run_mocha": "mocha 'lib/test/**/*.js' --timeout 10000 --bail --exit", "run_mocha": "mocha 'lib/test/**/*.js' --timeout 10000 --bail --exit",
"compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846", "compile:comment": "Yarn workspaces do not link binaries correctly so we need to reference them directly https://github.com/yarnpkg/yarn/issues/3846",
"compile": "node ../deployer/lib/src/cli.js compile", "compile": "node ../deployer/lib/src/cli.js compile --contracts-dir src/contracts --artifacts-dir src/artifacts",
"clean": "rm -rf ./lib", "clean": "rm -rf ./lib",
"generate_contract_wrappers": "node ../abi-gen/lib/index.js --abis 'src/artifacts/@(DummyToken|TokenTransferProxy|Exchange|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken).json' --template contract_templates/contract.handlebars --partials 'contract_templates/partials/**/*.handlebars' --output src/contract_wrappers/generated",
"migrate": "node ../deployer/lib/src/cli.js migrate", "migrate": "node ../deployer/lib/src/cli.js migrate",
"lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'", "lint": "tslint --project . 'migrations/**/*.ts' 'test/**/*.ts' 'util/**/*.ts' 'deploy/**/*.ts'",
"test:circleci": "yarn test" "test:circleci": "yarn test"

View File

@ -0,0 +1,8 @@
dummy_token.ts
exchange.ts
multi_sig_wallet_with_time_lock_except_remove_authorized_address.ts
multi_sig_wallet_with_time_lock.ts
multi_sig_wallet.ts
token_registry.ts
token_transfer_proxy.ts
zrx_token.ts

View File

@ -0,0 +1,35 @@
import {TxData, TxDataPayable} from '@0xproject/types';
import * as _ from 'lodash';
import * as Web3 from 'web3';
export class BaseContract {
public address: string;
protected _web3ContractInstance: Web3.ContractInstance;
protected _defaults: Partial<TxData>;
protected async _applyDefaultsToTxDataAsync<T extends TxData|TxDataPayable>(
txData: T,
estimateGasAsync?: (txData: T) => Promise<number>,
): Promise<TxData> {
// Gas amount sourced with the following priorities:
// 1. Optional param passed in to public method call
// 2. Global config passed in at library instantiation
// 3. Gas estimate calculation + safety margin
const removeUndefinedProperties = _.pickBy;
const txDataWithDefaults = {
...removeUndefinedProperties(this._defaults),
...removeUndefinedProperties(txData as any),
// HACK: TS can't prove that T is spreadable.
// Awaiting https://github.com/Microsoft/TypeScript/pull/13288 to be merged
};
if (_.isUndefined(txDataWithDefaults.gas) && !_.isUndefined(estimateGasAsync)) {
const estimatedGas = await estimateGasAsync(txData);
txDataWithDefaults.gas = estimatedGas;
}
return txDataWithDefaults;
}
constructor(web3ContractInstance: Web3.ContractInstance, defaults?: Partial<TxData>) {
this.address = web3ContractInstance.address;
this._web3ContractInstance = web3ContractInstance;
this._defaults = defaults || {};
}
}

View File

@ -13,6 +13,9 @@ import * as chai from 'chai';
import ethUtil = require('ethereumjs-util'); import ethUtil = require('ethereumjs-util');
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { Balances } from '../../util/balances'; import { Balances } from '../../util/balances';
import { constants } from '../../util/constants'; import { constants } from '../../util/constants';
import { crypto } from '../../util/crypto'; import { crypto } from '../../util/crypto';
@ -37,11 +40,11 @@ describe('Exchange', () => {
const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); const INITIAL_BALANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); const INITIAL_ALLOWANCE = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
let rep: Web3.ContractInstance; let rep: DummyTokenContract;
let dgd: Web3.ContractInstance; let dgd: DummyTokenContract;
let zrx: Web3.ContractInstance; let zrx: DummyTokenContract;
let exchange: Web3.ContractInstance; let exchange: ExchangeContract;
let tokenTransferProxy: Web3.ContractInstance; let tokenTransferProxy: TokenTransferProxyContract;
let order: Order; let order: Order;
let balances: BalancesByOwner; let balances: BalancesByOwner;
@ -55,14 +58,22 @@ describe('Exchange', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
maker = accounts[0]; maker = accounts[0];
[tokenOwner, taker, feeRecipient] = accounts; [tokenOwner, taker, feeRecipient] = accounts;
[rep, dgd, zrx] = await Promise.all([ const [repInstance, dgdInstance, zrxInstance] = await Promise.all([
deployer.deployAsync(ContractName.DummyToken), deployer.deployAsync(ContractName.DummyToken),
deployer.deployAsync(ContractName.DummyToken), deployer.deployAsync(ContractName.DummyToken),
deployer.deployAsync(ContractName.DummyToken), deployer.deployAsync(ContractName.DummyToken),
]); ]);
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); rep = new DummyTokenContract(repInstance);
exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]); dgd = new DummyTokenContract(dgdInstance);
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] }); zrx = new DummyTokenContract(zrxInstance);
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
zrx.address,
tokenTransferProxy.address,
]);
exchange = new ExchangeContract(exchangeInstance);
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
zeroEx = new ZeroEx(web3.currentProvider, { zeroEx = new ZeroEx(web3.currentProvider, {
exchangeContractAddress: exchange.address, exchangeContractAddress: exchange.address,
networkId: constants.TESTRPC_NETWORK_ID, networkId: constants.TESTRPC_NETWORK_ID,
@ -83,30 +94,30 @@ describe('Exchange', () => {
orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams); orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams);
dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]); dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]);
await Promise.all([ await Promise.all([
rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { rep.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: maker, from: maker,
}), }),
rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { rep.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: taker, from: taker,
}), }),
rep.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }), rep.setBalance.sendTransactionAsync(maker, INITIAL_BALANCE, { from: tokenOwner }),
rep.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }), rep.setBalance.sendTransactionAsync(taker, INITIAL_BALANCE, { from: tokenOwner }),
dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: maker, from: maker,
}), }),
dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: taker, from: taker,
}), }),
dgd.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }), dgd.setBalance.sendTransactionAsync(maker, INITIAL_BALANCE, { from: tokenOwner }),
dgd.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }), dgd.setBalance.sendTransactionAsync(taker, INITIAL_BALANCE, { from: tokenOwner }),
zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: maker, from: maker,
}), }),
zrx.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: taker, from: taker,
}), }),
zrx.setBalance(maker, INITIAL_BALANCE, { from: tokenOwner }), zrx.setBalance.sendTransactionAsync(maker, INITIAL_BALANCE, { from: tokenOwner }),
zrx.setBalance(taker, INITIAL_BALANCE, { from: tokenOwner }), zrx.setBalance.sendTransactionAsync(taker, INITIAL_BALANCE, { from: tokenOwner }),
]); ]);
}); });
beforeEach(async () => { beforeEach(async () => {
@ -117,19 +128,19 @@ describe('Exchange', () => {
}); });
describe('internal functions', () => { describe('internal functions', () => {
it('should include transferViaTokenTransferProxy', () => { it('should include transferViaTokenTransferProxy', () => {
expect(exchange.transferViaTokenTransferProxy).to.be.undefined(); expect((exchange as any).transferViaTokenTransferProxy).to.be.undefined();
}); });
it('should include isTransferable', () => { it('should include isTransferable', () => {
expect(exchange.isTransferable).to.be.undefined(); expect((exchange as any).isTransferable).to.be.undefined();
}); });
it('should include getBalance', () => { it('should include getBalance', () => {
expect(exchange.getBalance).to.be.undefined(); expect((exchange as any).getBalance).to.be.undefined();
}); });
it('should include getAllowance', () => { it('should include getAllowance', () => {
expect(exchange.getAllowance).to.be.undefined(); expect((exchange as any).getAllowance).to.be.undefined();
}); });
}); });
@ -565,9 +576,9 @@ describe('Exchange', () => {
it('should not change balances if maker allowances are too low to fill order and \ it('should not change balances if maker allowances are too low to fill order and \
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
await rep.approve(tokenTransferProxy.address, 0, { from: maker }); await rep.approve.sendTransactionAsync(tokenTransferProxy.address, new BigNumber(0), { from: maker });
await exWrapper.fillOrderAsync(order, taker); await exWrapper.fillOrderAsync(order, taker);
await rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { await rep.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: maker, from: maker,
}); });
@ -577,22 +588,22 @@ describe('Exchange', () => {
it('should throw if maker allowances are too low to fill order and \ it('should throw if maker allowances are too low to fill order and \
shouldThrowOnInsufficientBalanceOrAllowance = true', async () => { shouldThrowOnInsufficientBalanceOrAllowance = true', async () => {
await rep.approve(tokenTransferProxy.address, 0, { from: maker }); await rep.approve.sendTransactionAsync(tokenTransferProxy.address, new BigNumber(0), { from: maker });
expect( expect(
exWrapper.fillOrderAsync(order, taker, { exWrapper.fillOrderAsync(order, taker, {
shouldThrowOnInsufficientBalanceOrAllowance: true, shouldThrowOnInsufficientBalanceOrAllowance: true,
}), }),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
await rep.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { await rep.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: maker, from: maker,
}); });
}); });
it('should not change balances if taker allowances are too low to fill order and \ it('should not change balances if taker allowances are too low to fill order and \
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
await dgd.approve(tokenTransferProxy.address, 0, { from: taker }); await dgd.approve.sendTransactionAsync(tokenTransferProxy.address, new BigNumber(0), { from: taker });
await exWrapper.fillOrderAsync(order, taker); await exWrapper.fillOrderAsync(order, taker);
await dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { await dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: taker, from: taker,
}); });
@ -602,13 +613,13 @@ describe('Exchange', () => {
it('should throw if taker allowances are too low to fill order and \ it('should throw if taker allowances are too low to fill order and \
shouldThrowOnInsufficientBalanceOrAllowance = true', async () => { shouldThrowOnInsufficientBalanceOrAllowance = true', async () => {
await dgd.approve(tokenTransferProxy.address, 0, { from: taker }); await dgd.approve.sendTransactionAsync(tokenTransferProxy.address, new BigNumber(0), { from: taker });
expect( expect(
exWrapper.fillOrderAsync(order, taker, { exWrapper.fillOrderAsync(order, taker, {
shouldThrowOnInsufficientBalanceOrAllowance: true, shouldThrowOnInsufficientBalanceOrAllowance: true,
}), }),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
await dgd.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { await dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: taker, from: taker,
}); });
}); });
@ -668,7 +679,9 @@ describe('Exchange', () => {
it('should throw if getBalance or getAllowance attempts to change state and \ it('should throw if getBalance or getAllowance attempts to change state and \
shouldThrowOnInsufficientBalanceOrAllowance = false', async () => { shouldThrowOnInsufficientBalanceOrAllowance = false', async () => {
const maliciousToken = await deployer.deployAsync(ContractName.MaliciousToken); const maliciousToken = await deployer.deployAsync(ContractName.MaliciousToken);
await maliciousToken.approve(tokenTransferProxy.address, INITIAL_ALLOWANCE, { from: taker }); await maliciousToken.approve.sendTransactionAsync(tokenTransferProxy.address, INITIAL_ALLOWANCE, {
from: taker,
});
order = await orderFactory.newSignedOrderAsync({ order = await orderFactory.newSignedOrderAsync({
takerToken: maliciousToken.address, takerToken: maliciousToken.address,

View File

@ -5,6 +5,7 @@ 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 { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
import { constants } from '../../util/constants'; import { constants } from '../../util/constants';
import { ExchangeWrapper } from '../../util/exchange_wrapper'; import { ExchangeWrapper } from '../../util/exchange_wrapper';
import { Order } from '../../util/order'; import { Order } from '../../util/order';
@ -38,7 +39,11 @@ describe('Exchange', () => {
deployer.deployAsync(ContractName.DummyToken), deployer.deployAsync(ContractName.DummyToken),
deployer.deployAsync(ContractName.DummyToken), deployer.deployAsync(ContractName.DummyToken),
]); ]);
const exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]); const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
zrx.address,
tokenTransferProxy.address,
]);
const exchange = new ExchangeContract(exchangeInstance);
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] }); await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] });
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID }); const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
exchangeWrapper = new ExchangeWrapper(exchange, zeroEx); exchangeWrapper = new ExchangeWrapper(exchange, zeroEx);

View File

@ -6,6 +6,10 @@ import * as chai from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
import { ExchangeContract } from '../../src/contract_wrappers/generated/exchange';
import { TokenRegistryContract } from '../../src/contract_wrappers/generated/token_registry';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { Balances } from '../../util/balances'; import { Balances } from '../../util/balances';
import { constants } from '../../util/constants'; import { constants } from '../../util/constants';
import { ExchangeWrapper } from '../../util/exchange_wrapper'; import { ExchangeWrapper } from '../../util/exchange_wrapper';
@ -30,12 +34,12 @@ describe('Exchange', () => {
const INIT_BAL = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); const INIT_BAL = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
const INIT_ALLOW = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18); const INIT_ALLOW = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
let rep: Web3.ContractInstance; let rep: DummyTokenContract;
let dgd: Web3.ContractInstance; let dgd: DummyTokenContract;
let zrx: Web3.ContractInstance; let zrx: DummyTokenContract;
let exchange: Web3.ContractInstance; let exchange: ExchangeContract;
let tokenRegistry: Web3.ContractInstance; let tokenRegistry: TokenRegistryContract;
let tokenTransferProxy: Web3.ContractInstance; let tokenTransferProxy: TokenTransferProxyContract;
let balances: BalancesByOwner; let balances: BalancesByOwner;
@ -47,15 +51,24 @@ describe('Exchange', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
tokenOwner = accounts[0]; tokenOwner = accounts[0];
[maker, taker, feeRecipient] = accounts; [maker, taker, feeRecipient] = accounts;
[rep, dgd, zrx] = await Promise.all([ const [repInstance, dgdInstance, zrxInstance] = await Promise.all([
deployer.deployAsync(ContractName.DummyToken), deployer.deployAsync(ContractName.DummyToken),
deployer.deployAsync(ContractName.DummyToken), deployer.deployAsync(ContractName.DummyToken),
deployer.deployAsync(ContractName.DummyToken), deployer.deployAsync(ContractName.DummyToken),
]); ]);
tokenRegistry = await deployer.deployAsync(ContractName.TokenRegistry); rep = new DummyTokenContract(repInstance);
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); dgd = new DummyTokenContract(dgdInstance);
exchange = await deployer.deployAsync(ContractName.Exchange, [zrx.address, tokenTransferProxy.address]); zrx = new DummyTokenContract(zrxInstance);
await tokenTransferProxy.addAuthorizedAddress(exchange.address, { from: accounts[0] }); const tokenRegistryInstance = await deployer.deployAsync(ContractName.TokenRegistry);
tokenRegistry = new TokenRegistryContract(tokenRegistryInstance);
const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
const exchangeInstance = await deployer.deployAsync(ContractName.Exchange, [
zrx.address,
tokenTransferProxy.address,
]);
exchange = new ExchangeContract(exchangeInstance);
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(exchange.address, { from: accounts[0] });
const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID }); const zeroEx = new ZeroEx(web3.currentProvider, { networkId: constants.TESTRPC_NETWORK_ID });
exWrapper = new ExchangeWrapper(exchange, zeroEx); exWrapper = new ExchangeWrapper(exchange, zeroEx);
@ -74,18 +87,18 @@ describe('Exchange', () => {
orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams); orderFactory = new OrderFactory(web3Wrapper, defaultOrderParams);
dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]); dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]);
await Promise.all([ await Promise.all([
rep.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }), rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
rep.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }), rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
rep.setBalance(maker, INIT_BAL, { from: tokenOwner }), rep.setBalance.sendTransactionAsync(maker, INIT_BAL, { from: tokenOwner }),
rep.setBalance(taker, INIT_BAL, { from: tokenOwner }), rep.setBalance.sendTransactionAsync(taker, INIT_BAL, { from: tokenOwner }),
dgd.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }), dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
dgd.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }), dgd.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
dgd.setBalance(maker, INIT_BAL, { from: tokenOwner }), dgd.setBalance.sendTransactionAsync(maker, INIT_BAL, { from: tokenOwner }),
dgd.setBalance(taker, INIT_BAL, { from: tokenOwner }), dgd.setBalance.sendTransactionAsync(taker, INIT_BAL, { from: tokenOwner }),
zrx.approve(tokenTransferProxy.address, INIT_ALLOW, { from: maker }), zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: maker }),
zrx.approve(tokenTransferProxy.address, INIT_ALLOW, { from: taker }), zrx.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, { from: taker }),
zrx.setBalance(maker, INIT_BAL, { from: tokenOwner }), zrx.setBalance.sendTransactionAsync(maker, INIT_BAL, { from: tokenOwner }),
zrx.setBalance(taker, INIT_BAL, { from: tokenOwner }), zrx.setBalance.sendTransactionAsync(taker, INIT_BAL, { from: tokenOwner }),
]); ]);
}); });
beforeEach(async () => { beforeEach(async () => {

View File

@ -6,6 +6,8 @@ import * as chai from 'chai';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import * as multiSigWalletJSON from '../../build/contracts/MultiSigWalletWithTimeLock.json'; import * as multiSigWalletJSON from '../../build/contracts/MultiSigWalletWithTimeLock.json';
import { MultiSigWalletContract } from '../src/contract_wrappers/generated/multi_sig_wallet';
import { MultiSigWalletWithTimeLockContract } from '../src/contract_wrappers/generated/multi_sig_wallet_with_time_lock';
import { artifacts } from '../util/artifacts'; import { artifacts } from '../util/artifacts';
import { constants } from '../util/constants'; import { constants } from '../util/constants';
import { MultiSigWrapper } from '../util/multi_sig_wrapper'; import { MultiSigWrapper } from '../util/multi_sig_wrapper';
@ -30,12 +32,12 @@ describe('MultiSigWalletWithTimeLock', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
owners = [accounts[0], accounts[1]]; owners = [accounts[0], accounts[1]];
}); });
const SIGNATURES_REQUIRED = 2; const SIGNATURES_REQUIRED = new BigNumber(2);
const SECONDS_TIME_LOCKED = 10000; const SECONDS_TIME_LOCKED = new BigNumber(10000);
let multiSig: Web3.ContractInstance; let multiSig: MultiSigWalletWithTimeLockContract;
let multiSigWrapper: MultiSigWrapper; let multiSigWrapper: MultiSigWrapper;
let txId: number; let txId: BigNumber;
let initialSecondsTimeLocked: number; let initialSecondsTimeLocked: number;
let rpc: RPC; let rpc: RPC;
@ -52,20 +54,21 @@ describe('MultiSigWalletWithTimeLock', () => {
describe('changeTimeLock', () => { describe('changeTimeLock', () => {
describe('initially non-time-locked', async () => { describe('initially non-time-locked', async () => {
before('deploy a walet', async () => { before('deploy a walet', async () => {
multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [ const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
owners, owners,
SIGNATURES_REQUIRED, SIGNATURES_REQUIRED,
0, 0,
]); ]);
multiSigWrapper = new MultiSigWrapper(multiSig); multiSig = new MultiSigWalletWithTimeLockContract(multiSigInstance);
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
const secondsTimeLocked = await multiSig.secondsTimeLocked(); const secondsTimeLocked = await multiSig.secondsTimeLocked();
initialSecondsTimeLocked = secondsTimeLocked.toNumber(); initialSecondsTimeLocked = secondsTimeLocked.toNumber();
}); });
it('should throw when not called by wallet', async () => { it('should throw when not called by wallet', async () => {
return expect(multiSig.changeTimeLock(SECONDS_TIME_LOCKED, { from: owners[0] })).to.be.rejectedWith( return expect(
constants.REVERT, 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 () => {
@ -74,7 +77,7 @@ describe('MultiSigWalletWithTimeLock', () => {
const dataParams = { const dataParams = {
name: 'changeTimeLock', name: 'changeTimeLock',
abi: MULTI_SIG_ABI, abi: MULTI_SIG_ABI,
args: [SECONDS_TIME_LOCKED], args: [SECONDS_TIME_LOCKED.toNumber()],
}; };
const txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); const txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
@ -82,10 +85,10 @@ describe('MultiSigWalletWithTimeLock', () => {
SubmissionContractEventArgs SubmissionContractEventArgs
>; >;
txId = log.args.transactionId.toNumber(); txId = log.args.transactionId;
return expect(multiSig.executeTransaction(txId, { from: owners[0] })).to.be.rejectedWith( return expect(
constants.REVERT, 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 () => {
@ -94,7 +97,7 @@ describe('MultiSigWalletWithTimeLock', () => {
const dataParams = { const dataParams = {
name: 'changeTimeLock', name: 'changeTimeLock',
abi: MULTI_SIG_ABI, abi: MULTI_SIG_ABI,
args: [SECONDS_TIME_LOCKED], args: [SECONDS_TIME_LOCKED.toNumber()],
}; };
let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
@ -102,15 +105,15 @@ describe('MultiSigWalletWithTimeLock', () => {
SubmissionContractEventArgs SubmissionContractEventArgs
>; >;
txId = log.args.transactionId.toNumber(); txId = log.args.transactionId;
txHash = await multiSig.confirmTransaction(txId, { from: owners[1] }); txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
const res = await zeroEx.awaitTransactionMinedAsync(txHash); const res = await zeroEx.awaitTransactionMinedAsync(txHash);
expect(res.logs).to.have.length(2); expect(res.logs).to.have.length(2);
const blockNum = await web3Wrapper.getBlockNumberAsync(); const blockNum = await web3Wrapper.getBlockNumberAsync();
const blockInfo = await web3Wrapper.getBlockAsync(blockNum); const blockInfo = await web3Wrapper.getBlockAsync(blockNum);
const timestamp = new BigNumber(blockInfo.timestamp); const timestamp = new BigNumber(blockInfo.timestamp);
const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.call(txId)); const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes(txId));
expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum); expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
}); });
@ -121,7 +124,7 @@ describe('MultiSigWalletWithTimeLock', () => {
const dataParams = { const dataParams = {
name: 'changeTimeLock', name: 'changeTimeLock',
abi: MULTI_SIG_ABI, abi: MULTI_SIG_ABI,
args: [SECONDS_TIME_LOCKED], args: [SECONDS_TIME_LOCKED.toNumber()],
}; };
let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
const subRes = await zeroEx.awaitTransactionMinedAsync(txHash); const subRes = await zeroEx.awaitTransactionMinedAsync(txHash);
@ -129,27 +132,28 @@ describe('MultiSigWalletWithTimeLock', () => {
SubmissionContractEventArgs SubmissionContractEventArgs
>; >;
txId = log.args.transactionId.toNumber(); txId = log.args.transactionId;
txHash = await multiSig.confirmTransaction(txId, { from: owners[1] }); txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
expect(initialSecondsTimeLocked).to.be.equal(0); expect(initialSecondsTimeLocked).to.be.equal(0);
txHash = await multiSig.executeTransaction(txId, { from: owners[0] }); txHash = await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] });
const res = await zeroEx.awaitTransactionMinedAsync(txHash); const res = await zeroEx.awaitTransactionMinedAsync(txHash);
expect(res.logs).to.have.length(2); expect(res.logs).to.have.length(2);
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call()); const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked());
expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED); expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
}); });
}); });
describe('initially time-locked', async () => { describe('initially time-locked', async () => {
before('deploy a walet', async () => { before('deploy a walet', async () => {
multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [ const multiSigInstance = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLock, [
owners, owners,
SIGNATURES_REQUIRED, SIGNATURES_REQUIRED,
SECONDS_TIME_LOCKED, SECONDS_TIME_LOCKED,
]); ]);
multiSigWrapper = new MultiSigWrapper(multiSig); multiSig = new MultiSigWalletWithTimeLockContract(multiSigInstance);
multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
const secondsTimeLocked = await multiSig.secondsTimeLocked(); const secondsTimeLocked = await multiSig.secondsTimeLocked();
initialSecondsTimeLocked = secondsTimeLocked.toNumber(); initialSecondsTimeLocked = secondsTimeLocked.toNumber();
@ -165,8 +169,8 @@ describe('MultiSigWalletWithTimeLock', () => {
const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs< const log = abiDecoder.tryToDecodeLogOrNoop(subRes.logs[0]) as LogWithDecodedArgs<
SubmissionContractEventArgs SubmissionContractEventArgs
>; >;
txId = log.args.transactionId.toNumber(); txId = log.args.transactionId;
txHash = await multiSig.confirmTransaction(txId, { txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, {
from: owners[1], from: owners[1],
}); });
const confRes = await zeroEx.awaitTransactionMinedAsync(txHash); const confRes = await zeroEx.awaitTransactionMinedAsync(txHash);
@ -174,16 +178,16 @@ describe('MultiSigWalletWithTimeLock', () => {
}); });
const newSecondsTimeLocked = 0; const newSecondsTimeLocked = 0;
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(multiSig.executeTransaction(txId, { from: owners[0] })).to.be.rejectedWith( return expect(
constants.REVERT, 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 rpc.increaseTimeAsync(SECONDS_TIME_LOCKED); await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber());
await multiSig.executeTransaction(txId, { from: owners[0] }); await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] });
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call()); const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked());
expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked); expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
}); });
}); });

View File

@ -5,6 +5,9 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { MultiSigWalletContract } from '../src/contract_wrappers/generated/multi_sig_wallet';
import { MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract } from '../src/contract_wrappers/generated/multi_sig_wallet_with_time_lock_except_remove_authorized_address';
import { TokenTransferProxyContract } from '../src/contract_wrappers/generated/token_transfer_proxy';
import { artifacts } from '../util/artifacts'; import { artifacts } from '../util/artifacts';
import { constants } from '../util/constants'; import { constants } from '../util/constants';
import { crypto } from '../util/crypto'; import { crypto } from '../util/crypto';
@ -35,8 +38,8 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
let authorizedAddress: string; let authorizedAddress: string;
let unauthorizedAddress: string; let unauthorizedAddress: string;
let tokenTransferProxy: Web3.ContractInstance; let tokenTransferProxy: TokenTransferProxyContract;
let multiSig: Web3.ContractInstance; let multiSig: MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract;
let multiSigWrapper: MultiSigWrapper; let multiSigWrapper: MultiSigWrapper;
let validDestination: string; let validDestination: string;
@ -45,20 +48,20 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
owners = [accounts[0], accounts[1]]; owners = [accounts[0], accounts[1]];
[authorizedAddress, unauthorizedAddress] = accounts; [authorizedAddress, unauthorizedAddress] = accounts;
const initialOwner = accounts[0]; const initialOwner = accounts[0];
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
await tokenTransferProxy.addAuthorizedAddress(authorizedAddress, { tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(authorizedAddress, {
from: initialOwner, from: initialOwner,
}); });
multiSig = await deployer.deployAsync(ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress, [ const multiSigInstance = await deployer.deployAsync(
owners, ContractName.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress,
requiredApprovals, [owners, requiredApprovals, SECONDS_TIME_LOCKED, tokenTransferProxy.address],
SECONDS_TIME_LOCKED, );
tokenTransferProxy.address, multiSig = new MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract(multiSigInstance);
]); await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, {
await tokenTransferProxy.transferOwnership(multiSig.address, {
from: initialOwner, from: initialOwner,
}); });
multiSigWrapper = new MultiSigWrapper(multiSig); multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract);
validDestination = tokenTransferProxy.address; validDestination = tokenTransferProxy.address;
}); });
beforeEach(async () => { beforeEach(async () => {
@ -71,12 +74,12 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
describe('isFunctionRemoveAuthorizedAddress', () => { describe('isFunctionRemoveAuthorizedAddress', () => {
it('should throw if data is not for removeAuthorizedAddress', async () => { it('should throw if data is not for removeAuthorizedAddress', async () => {
const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]); const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]);
return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data)).to.be.rejectedWith(constants.REVERT); return expect(multiSig.isFunctionRemoveAuthorizedAddress(data)).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 () => {
const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]); const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]);
const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.call(data); const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress(data);
expect(isFunctionRemoveAuthorizedAddress).to.be.true(); expect(isFunctionRemoveAuthorizedAddress).to.be.true();
}); });
}); });
@ -91,11 +94,11 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const res = await zeroEx.awaitTransactionMinedAsync(txHash); const res = await zeroEx.awaitTransactionMinedAsync(txHash);
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
const txId = log.args.transactionId.toString(); const txId = log.args.transactionId;
return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith( return expect(
constants.REVERT, multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
); ).to.be.rejectedWith(constants.REVERT);
}); });
it('should throw if tx destination is not the tokenTransferProxy', async () => { it('should throw if tx destination is not the tokenTransferProxy', async () => {
@ -109,14 +112,14 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
const txHash = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams); const txHash = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams);
const res = await zeroEx.awaitTransactionMinedAsync(txHash); const res = await zeroEx.awaitTransactionMinedAsync(txHash);
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
const txId = log.args.transactionId.toString(); const txId = log.args.transactionId;
await multiSig.confirmTransaction(txId, { from: owners[1] }); await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
const isConfirmed = await multiSig.isConfirmed.call(txId); const isConfirmed = await multiSig.isConfirmed(txId);
expect(isConfirmed).to.be.true(); expect(isConfirmed).to.be.true();
return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith( return expect(
constants.REVERT, 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 () => {
@ -128,14 +131,14 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const res = await zeroEx.awaitTransactionMinedAsync(txHash); const res = await zeroEx.awaitTransactionMinedAsync(txHash);
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
const txId = log.args.transactionId.toString(); const txId = log.args.transactionId;
await multiSig.confirmTransaction(txId, { from: owners[1] }); await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
const isConfirmed = await multiSig.isConfirmed.call(txId); const isConfirmed = await multiSig.isConfirmed(txId);
expect(isConfirmed).to.be.true(); expect(isConfirmed).to.be.true();
return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith( return expect(
constants.REVERT, multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
); ).to.be.rejectedWith(constants.REVERT);
}); });
it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => { it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => {
@ -147,12 +150,12 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const res = await zeroEx.awaitTransactionMinedAsync(txHash); const res = await zeroEx.awaitTransactionMinedAsync(txHash);
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
const txId = log.args.transactionId.toString(); const txId = log.args.transactionId;
await multiSig.confirmTransaction(txId, { from: owners[1] }); await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
const isConfirmed = await multiSig.isConfirmed.call(txId); const isConfirmed = await multiSig.isConfirmed(txId);
expect(isConfirmed).to.be.true(); expect(isConfirmed).to.be.true();
await multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] }); await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] });
const isAuthorized = await tokenTransferProxy.authorized.call(authorizedAddress); const isAuthorized = await tokenTransferProxy.authorized(authorizedAddress);
expect(isAuthorized).to.be.false(); expect(isAuthorized).to.be.false();
}); });
@ -165,17 +168,17 @@ describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => {
const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const res = await zeroEx.awaitTransactionMinedAsync(txHash); const res = await zeroEx.awaitTransactionMinedAsync(txHash);
const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>;
const txId = log.args.transactionId.toString(); const txId = log.args.transactionId;
await multiSig.confirmTransaction(txId, { from: owners[1] }); await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] });
const isConfirmed = await multiSig.isConfirmed(txId); const isConfirmed = await multiSig.isConfirmed(txId);
expect(isConfirmed).to.be.true(); expect(isConfirmed).to.be.true();
await multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] }); await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] });
const tx = await multiSig.transactions(txId); const tx = await multiSig.transactions(txId);
const isExecuted = tx[3]; const isExecuted = tx[3];
expect(isExecuted).to.be.true(); expect(isExecuted).to.be.true();
return expect(multiSig.executeRemoveAuthorizedAddress(txId, { from: owners[1] })).to.be.rejectedWith( return expect(
constants.REVERT, multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }),
); ).to.be.rejectedWith(constants.REVERT);
}); });
}); });
}); });

View File

@ -1,11 +1,13 @@
import { ZeroEx } from '0x.js'; import { ZeroEx } from '0x.js';
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-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 ethUtil = require('ethereumjs-util'); import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { TokenRegistryContract } from '../src/contract_wrappers/generated/token_registry';
import { constants } from '../util/constants'; import { constants } from '../util/constants';
import { TokenRegWrapper } from '../util/token_registry_wrapper'; import { TokenRegWrapper } from '../util/token_registry_wrapper';
import { ContractName } from '../util/types'; import { ContractName } from '../util/types';
@ -22,13 +24,14 @@ const blockchainLifecycle = new BlockchainLifecycle();
describe('TokenRegistry', () => { describe('TokenRegistry', () => {
let owner: string; let owner: string;
let notOwner: string; let notOwner: string;
let tokenReg: Web3.ContractInstance; let tokenReg: TokenRegistryContract;
let tokenRegWrapper: TokenRegWrapper; let tokenRegWrapper: TokenRegWrapper;
before(async () => { before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = accounts[0]; owner = accounts[0];
notOwner = accounts[1]; notOwner = accounts[1];
tokenReg = await deployer.deployAsync(ContractName.TokenRegistry); const tokenRegInstance = await deployer.deployAsync(ContractName.TokenRegistry);
tokenReg = new TokenRegistryContract(tokenRegInstance);
tokenRegWrapper = new TokenRegWrapper(tokenReg); tokenRegWrapper = new TokenRegWrapper(tokenReg);
}); });
beforeEach(async () => { beforeEach(async () => {
@ -132,12 +135,12 @@ 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 expect(
tokenReg.setTokenName(token1.address, token2.name, { from: notOwner }), tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, { from: notOwner }),
).to.be.rejectedWith(constants.REVERT); ).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 () => {
await tokenReg.setTokenName(token1.address, token2.name, { await tokenReg.setTokenName.sendTransactionAsync(token1.address, token2.name, {
from: owner, from: owner,
}); });
const [newData, oldData] = await Promise.all([ const [newData, oldData] = await Promise.all([
@ -154,14 +157,14 @@ 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(tokenReg.setTokenName(token1.address, token2.name, { from: owner })).to.be.rejectedWith( return expect(
constants.REVERT, 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 expect(
tokenReg.setTokenName(nullToken.address, token2.name, { from: owner }), tokenReg.setTokenName.sendTransactionAsync(nullToken.address, token2.name, { from: owner }),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
}); });
}); });
@ -169,14 +172,14 @@ describe('TokenRegistry', () => {
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 expect(
tokenReg.setTokenSymbol(token1.address, token2.symbol, { tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, {
from: notOwner, from: notOwner,
}), }),
).to.be.rejectedWith(constants.REVERT); ).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 () => {
await tokenReg.setTokenSymbol(token1.address, token2.symbol, { from: owner }); await tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, { from: owner });
const [newData, oldData] = await Promise.all([ const [newData, oldData] = await Promise.all([
tokenRegWrapper.getTokenBySymbolAsync(token2.symbol), tokenRegWrapper.getTokenBySymbolAsync(token2.symbol),
tokenRegWrapper.getTokenBySymbolAsync(token1.symbol), tokenRegWrapper.getTokenBySymbolAsync(token1.symbol),
@ -192,7 +195,7 @@ describe('TokenRegistry', () => {
await tokenRegWrapper.addTokenAsync(token2, owner); await tokenRegWrapper.addTokenAsync(token2, owner);
return expect( return expect(
tokenReg.setTokenSymbol(token1.address, token2.symbol, { tokenReg.setTokenSymbol.sendTransactionAsync(token1.address, token2.symbol, {
from: owner, from: owner,
}), }),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
@ -200,7 +203,7 @@ describe('TokenRegistry', () => {
it('should throw if token does not exist', async () => { it('should throw if token does not exist', async () => {
return expect( return expect(
tokenReg.setTokenSymbol(nullToken.address, token2.symbol, { tokenReg.setTokenSymbol.sendTransactionAsync(nullToken.address, token2.symbol, {
from: owner, from: owner,
}), }),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
@ -209,15 +212,15 @@ describe('TokenRegistry', () => {
describe('removeToken', () => { describe('removeToken', () => {
it('should throw if not called by owner', async () => { it('should throw if not called by owner', async () => {
const index = 0; const index = new BigNumber(0);
return expect(tokenReg.removeToken(token1.address, index, { from: notOwner })).to.be.rejectedWith( return expect(
constants.REVERT, 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 () => {
const index = 0; const index = new BigNumber(0);
await tokenReg.removeToken(token1.address, index, { await tokenReg.removeToken.sendTransactionAsync(token1.address, index, {
from: owner, from: owner,
}); });
const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address); const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address);
@ -225,18 +228,18 @@ describe('TokenRegistry', () => {
}); });
it('should throw if token does not exist', async () => { it('should throw if token does not exist', async () => {
const index = 0; const index = new BigNumber(0);
return expect(tokenReg.removeToken(nullToken.address, index, { from: owner })).to.be.rejectedWith( return expect(
constants.REVERT, 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 = 0; const incorrectIndex = new BigNumber(0);
return expect(tokenReg.removeToken(token2.address, incorrectIndex, { from: owner })).to.be.rejectedWith( return expect(
constants.REVERT, tokenReg.removeToken.sendTransactionAsync(token2.address, incorrectIndex, { from: owner }),
); ).to.be.rejectedWith(constants.REVERT);
}); });
}); });
}); });

View File

@ -3,6 +3,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { constants } from '../../util/constants'; import { constants } from '../../util/constants';
import { ContractName } from '../../util/types'; import { ContractName } from '../../util/types';
import { chaiSetup } from '../utils/chai_setup'; import { chaiSetup } from '../utils/chai_setup';
@ -18,12 +19,13 @@ describe('TokenTransferProxy', () => {
let owner: string; let owner: string;
let notOwner: string; let notOwner: string;
let address: string; let address: string;
let tokenTransferProxy: Web3.ContractInstance; let tokenTransferProxy: TokenTransferProxyContract;
before(async () => { before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = address = accounts[0]; owner = address = accounts[0];
notOwner = accounts[1]; notOwner = accounts[1];
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
}); });
beforeEach(async () => { beforeEach(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
@ -33,36 +35,36 @@ describe('TokenTransferProxy', () => {
}); });
describe('addAuthorizedAddress', () => { describe('addAuthorizedAddress', () => {
it('should throw if not called by owner', async () => { it('should throw if not called by owner', async () => {
return expect(tokenTransferProxy.addAuthorizedAddress(notOwner, { from: notOwner })).to.be.rejectedWith( return expect(
constants.REVERT, tokenTransferProxy.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 tokenTransferProxy.addAuthorizedAddress(address, { from: owner }); await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
const isAuthorized = await tokenTransferProxy.authorized(address); const isAuthorized = await tokenTransferProxy.authorized(address);
expect(isAuthorized).to.be.true(); expect(isAuthorized).to.be.true();
}); });
it('should throw if owner attempts to authorize a duplicate address', async () => { it('should throw if owner attempts to authorize a duplicate address', async () => {
await tokenTransferProxy.addAuthorizedAddress(address, { from: owner }); await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
return expect(tokenTransferProxy.addAuthorizedAddress(address, { from: owner })).to.be.rejectedWith( return expect(
constants.REVERT, tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner }),
); ).to.be.rejectedWith(constants.REVERT);
}); });
}); });
describe('removeAuthorizedAddress', () => { describe('removeAuthorizedAddress', () => {
it('should throw if not called by owner', async () => { it('should throw if not called by owner', async () => {
await tokenTransferProxy.addAuthorizedAddress(address, { from: owner }); await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
return expect( return expect(
tokenTransferProxy.removeAuthorizedAddress(address, { tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
from: notOwner, from: notOwner,
}), }),
).to.be.rejectedWith(constants.REVERT); ).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 () => {
await tokenTransferProxy.addAuthorizedAddress(address, { from: owner }); await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, { from: owner });
await tokenTransferProxy.removeAuthorizedAddress(address, { await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
from: owner, from: owner,
}); });
const isAuthorized = await tokenTransferProxy.authorized(address); const isAuthorized = await tokenTransferProxy.authorized(address);
@ -71,7 +73,7 @@ describe('TokenTransferProxy', () => {
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 expect(
tokenTransferProxy.removeAuthorizedAddress(address, { tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
from: owner, from: owner,
}), }),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
@ -82,14 +84,14 @@ describe('TokenTransferProxy', () => {
it('should return all authorized addresses', async () => { it('should return all authorized addresses', async () => {
const initial = await tokenTransferProxy.getAuthorizedAddresses(); const initial = await tokenTransferProxy.getAuthorizedAddresses();
expect(initial).to.have.length(0); expect(initial).to.have.length(0);
await tokenTransferProxy.addAuthorizedAddress(address, { await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(address, {
from: owner, from: owner,
}); });
const afterAdd = await tokenTransferProxy.getAuthorizedAddresses(); const afterAdd = await tokenTransferProxy.getAuthorizedAddresses();
expect(afterAdd).to.have.length(1); expect(afterAdd).to.have.length(1);
expect(afterAdd).to.include(address); expect(afterAdd).to.include(address);
await tokenTransferProxy.removeAuthorizedAddress(address, { await tokenTransferProxy.removeAuthorizedAddress.sendTransactionAsync(address, {
from: owner, from: owner,
}); });
const afterRemove = await tokenTransferProxy.getAuthorizedAddresses(); const afterRemove = await tokenTransferProxy.getAuthorizedAddresses();

View File

@ -1,8 +1,11 @@
import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-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 Web3 from 'web3'; import * as Web3 from 'web3';
import { DummyTokenContract } from '../../src/contract_wrappers/generated/dummy_token';
import { TokenTransferProxyContract } from '../../src/contract_wrappers/generated/token_transfer_proxy';
import { Balances } from '../../util/balances'; import { Balances } from '../../util/balances';
import { constants } from '../../util/constants'; import { constants } from '../../util/constants';
import { ContractName } from '../../util/types'; import { ContractName } from '../../util/types';
@ -19,29 +22,31 @@ describe('TokenTransferProxy', () => {
let accounts: string[]; let accounts: string[];
let owner: string; let owner: string;
let notAuthorized: string; let notAuthorized: string;
const INIT_BAL = 100000000; const INIT_BAL = new BigNumber(100000000);
const INIT_ALLOW = 100000000; const INIT_ALLOW = new BigNumber(100000000);
let tokenTransferProxy: Web3.ContractInstance; let tokenTransferProxy: TokenTransferProxyContract;
let rep: Web3.ContractInstance; let rep: DummyTokenContract;
let dmyBalances: Balances; let dmyBalances: Balances;
before(async () => { before(async () => {
accounts = await web3Wrapper.getAvailableAddressesAsync(); accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = notAuthorized = accounts[0]; owner = notAuthorized = accounts[0];
tokenTransferProxy = await deployer.deployAsync(ContractName.TokenTransferProxy); const tokenTransferProxyInstance = await deployer.deployAsync(ContractName.TokenTransferProxy);
rep = await deployer.deployAsync(ContractName.DummyToken); tokenTransferProxy = new TokenTransferProxyContract(tokenTransferProxyInstance);
const repInstance = await deployer.deployAsync(ContractName.DummyToken);
rep = new DummyTokenContract(repInstance);
dmyBalances = new Balances([rep], [accounts[0], accounts[1]]); dmyBalances = new Balances([rep], [accounts[0], accounts[1]]);
await Promise.all([ await Promise.all([
rep.approve(tokenTransferProxy.address, INIT_ALLOW, { rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, {
from: accounts[0], from: accounts[0],
}), }),
rep.setBalance(accounts[0], INIT_BAL, { from: owner }), rep.setBalance.sendTransactionAsync(accounts[0], INIT_BAL, { from: owner }),
rep.approve(tokenTransferProxy.address, INIT_ALLOW, { rep.approve.sendTransactionAsync(tokenTransferProxy.address, INIT_ALLOW, {
from: accounts[1], from: accounts[1],
}), }),
rep.setBalance(accounts[1], INIT_BAL, { from: owner }), rep.setBalance.sendTransactionAsync(accounts[1], INIT_BAL, { from: owner }),
]); ]);
}); });
beforeEach(async () => { beforeEach(async () => {
@ -54,20 +59,34 @@ describe('TokenTransferProxy', () => {
describe('transferFrom', () => { describe('transferFrom', () => {
it('should throw when called by an unauthorized address', async () => { it('should throw when called by an unauthorized address', async () => {
expect( expect(
tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1], 1000, { from: notAuthorized }), tokenTransferProxy.transferFrom.sendTransactionAsync(
rep.address,
accounts[0],
accounts[1],
new BigNumber(1000),
{
from: notAuthorized,
},
),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
}); });
it('should allow an authorized address to transfer', async () => { it('should allow an authorized address to transfer', async () => {
const balances = await dmyBalances.getAsync(); const balances = await dmyBalances.getAsync();
await tokenTransferProxy.addAuthorizedAddress(notAuthorized, { await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(notAuthorized, {
from: owner, from: owner,
}); });
const transferAmt = 10000; const transferAmt = new BigNumber(10000);
await tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1], transferAmt, { await tokenTransferProxy.transferFrom.sendTransactionAsync(
from: notAuthorized, rep.address,
}); accounts[0],
accounts[1],
transferAmt,
{
from: notAuthorized,
},
);
const newBalances = await dmyBalances.getAsync(); const newBalances = await dmyBalances.getAsync();
expect(newBalances[accounts[0]][rep.address]).to.be.bignumber.equal( expect(newBalances[accounts[0]][rep.address]).to.be.bignumber.equal(

View File

@ -5,6 +5,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { DummyTokenContract } from '../src/contract_wrappers/generated/dummy_token';
import { constants } from '../util/constants'; import { constants } from '../util/constants';
import { ContractName } from '../util/types'; import { ContractName } from '../util/types';
@ -27,14 +28,15 @@ describe('UnlimitedAllowanceToken', () => {
const MAX_MINT_VALUE = new BigNumber(100000000000000000000); const MAX_MINT_VALUE = new BigNumber(100000000000000000000);
let tokenAddress: string; let tokenAddress: string;
let token: Web3.ContractInstance; let token: DummyTokenContract;
before(async () => { before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
owner = accounts[0]; owner = accounts[0];
spender = accounts[1]; spender = accounts[1];
token = await deployer.deployAsync(ContractName.DummyToken); const tokenInstance = await deployer.deployAsync(ContractName.DummyToken);
await token.mint(MAX_MINT_VALUE, { from: owner }); token = new DummyTokenContract(tokenInstance);
await token.mint.sendTransactionAsync(MAX_MINT_VALUE, { from: owner });
tokenAddress = token.address; tokenAddress = token.address;
}); });
beforeEach(async () => { beforeEach(async () => {
@ -47,7 +49,7 @@ describe('UnlimitedAllowanceToken', () => {
it('should throw if owner has insufficient balance', async () => { it('should throw if owner has insufficient balance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner); const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = ownerBalance.plus(1); const amountToTransfer = ownerBalance.plus(1);
return expect(token.transfer.call(spender, amountToTransfer, { from: owner })).to.be.rejectedWith( return expect(token.transfer.callAsync(spender, amountToTransfer, { from: owner })).to.be.rejectedWith(
constants.REVERT, constants.REVERT,
); );
}); });
@ -67,7 +69,7 @@ describe('UnlimitedAllowanceToken', () => {
}); });
it('should return true on a 0 value transfer', async () => { it('should return true on a 0 value transfer', async () => {
const didReturnTrue = await token.transfer.call(spender, 0, { const didReturnTrue = await token.transfer.callAsync(spender, new BigNumber(0), {
from: owner, from: owner,
}); });
expect(didReturnTrue).to.be.true(); expect(didReturnTrue).to.be.true();
@ -80,7 +82,7 @@ describe('UnlimitedAllowanceToken', () => {
const amountToTransfer = ownerBalance.plus(1); const amountToTransfer = ownerBalance.plus(1);
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer); await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer);
return expect( return expect(
token.transferFrom.call(owner, spender, amountToTransfer, { token.transferFrom.callAsync(owner, spender, amountToTransfer, {
from: spender, from: spender,
}), }),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
@ -95,15 +97,17 @@ describe('UnlimitedAllowanceToken', () => {
expect(spenderAllowanceIsInsufficient).to.be.true(); expect(spenderAllowanceIsInsufficient).to.be.true();
return expect( return expect(
token.transferFrom.call(owner, spender, amountToTransfer, { token.transferFrom.callAsync(owner, spender, amountToTransfer, {
from: spender, from: spender,
}), }),
).to.be.rejectedWith(constants.REVERT); ).to.be.rejectedWith(constants.REVERT);
}); });
it('should return true on a 0 value transfer', async () => { it('should return true on a 0 value transfer', async () => {
const amountToTransfer = 0; const amountToTransfer = new BigNumber(0);
const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, { from: spender }); const didReturnTrue = await token.transferFrom.callAsync(owner, spender, amountToTransfer, {
from: spender,
});
expect(didReturnTrue).to.be.true(); expect(didReturnTrue).to.be.true();
}); });

View File

@ -5,7 +5,7 @@ import * as path from 'path';
import { constants } from '../../util/constants'; import { constants } from '../../util/constants';
const deployerOpts = { const deployerOpts = {
artifactsDir: path.resolve('artifacts'), artifactsDir: path.resolve('src', 'artifacts'),
jsonrpcPort: devConstants.RPC_PORT, jsonrpcPort: devConstants.RPC_PORT,
networkId: constants.TESTRPC_NETWORK_ID, networkId: constants.TESTRPC_NETWORK_ID,
defaults: { defaults: {

View File

@ -5,6 +5,7 @@ import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as chai from 'chai'; import * as chai from 'chai';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { ZRXTokenContract } from '../src/contract_wrappers/generated/zrx_token';
import { constants } from '../util/constants'; import { constants } from '../util/constants';
import { ContractName } from '../util/types'; import { ContractName } from '../util/types';
@ -24,7 +25,7 @@ describe('ZRXToken', () => {
let MAX_UINT: BigNumber; let MAX_UINT: BigNumber;
let zrx: Web3.ContractInstance; let zrx: ZRXTokenContract;
let zrxAddress: string; let zrxAddress: string;
before(async () => { before(async () => {
@ -34,7 +35,8 @@ describe('ZRXToken', () => {
zeroEx = new ZeroEx(web3.currentProvider, { zeroEx = new ZeroEx(web3.currentProvider, {
networkId: constants.TESTRPC_NETWORK_ID, networkId: constants.TESTRPC_NETWORK_ID,
}); });
zrx = await deployer.deployAsync(ContractName.ZRXToken); const zrxInstance = await deployer.deployAsync(ContractName.ZRXToken);
zrx = new ZRXTokenContract(zrxInstance);
zrxAddress = zrx.address; zrxAddress = zrx.address;
MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS; MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
}); });
@ -94,7 +96,7 @@ describe('ZRXToken', () => {
}); });
it('should return true on a 0 value transfer', async () => { it('should return true on a 0 value transfer', async () => {
const didReturnTrue = await zrx.transfer.call(spender, 0, { const didReturnTrue = await zrx.transfer.callAsync(spender, new BigNumber(0), {
from: owner, from: owner,
}); });
expect(didReturnTrue).to.be.true(); expect(didReturnTrue).to.be.true();
@ -108,7 +110,7 @@ describe('ZRXToken', () => {
await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer, { await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer, {
gasLimit: constants.MAX_TOKEN_APPROVE_GAS, gasLimit: constants.MAX_TOKEN_APPROVE_GAS,
}); });
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, { from: spender }); const didReturnTrue = await zrx.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender });
expect(didReturnTrue).to.be.false(); expect(didReturnTrue).to.be.false();
}); });
@ -120,13 +122,13 @@ describe('ZRXToken', () => {
const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0; const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0;
expect(spenderAllowanceIsInsufficient).to.be.true(); expect(spenderAllowanceIsInsufficient).to.be.true();
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, { from: spender }); const didReturnTrue = await zrx.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender });
expect(didReturnTrue).to.be.false(); expect(didReturnTrue).to.be.false();
}); });
it('should return true on a 0 value transfer', async () => { it('should return true on a 0 value transfer', async () => {
const amountToTransfer = 0; const amountToTransfer = new BigNumber(0);
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, { from: spender }); const didReturnTrue = await zrx.transferFrom.callAsync(owner, spender, amountToTransfer, { from: spender });
expect(didReturnTrue).to.be.true(); expect(didReturnTrue).to.be.true();
}); });

View File

@ -4,6 +4,7 @@
"outDir": "lib", "outDir": "lib",
"baseUrl": ".", "baseUrl": ".",
"declaration": false, "declaration": false,
"noImplicitThis": false,
"allowJs": true "allowJs": true
}, },
"include": [ "include": [
@ -14,10 +15,10 @@
"../../node_modules/types-ethereumjs-util/index.d.ts", "../../node_modules/types-ethereumjs-util/index.d.ts",
"../../node_modules/types-bn/index.d.ts", "../../node_modules/types-bn/index.d.ts",
"./globals.d.ts", "./globals.d.ts",
"./src/**/*",
"./util/**/*", "./util/**/*",
"./test/**/*", "./test/**/*",
"./migrations/**/*", "./migrations/**/*"
"./deploy/**/*"
], ],
"exclude": ["./deploy/solc/solc_bin"] "exclude": ["./deploy/solc/solc_bin"]
} }

View File

@ -1,13 +1,13 @@
import * as DummyTokenArtifact from '../artifacts/DummyToken.json'; import * as DummyTokenArtifact from '../src/artifacts/DummyToken.json';
import * as ExchangeArtifact from '../artifacts/Exchange.json'; import * as ExchangeArtifact from '../src/artifacts/Exchange.json';
import * as MaliciousTokenArtifact from '../artifacts/MaliciousToken.json'; import * as MaliciousTokenArtifact from '../src/artifacts/MaliciousToken.json';
import * as MultiSigWalletWithTimeLockArtifact from '../artifacts/MultiSigWalletWithTimeLock.json'; import * as MultiSigWalletWithTimeLockArtifact from '../src/artifacts/MultiSigWalletWithTimeLock.json';
import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact from '../artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json'; import * as MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressArtifact from '../src/artifacts/MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.json';
import * as TokenArtifact from '../artifacts/Token.json'; import * as TokenArtifact from '../src/artifacts/Token.json';
import * as TokenRegistryArtifact from '../artifacts/TokenRegistry.json'; import * as TokenRegistryArtifact from '../src/artifacts/TokenRegistry.json';
import * as TokenTransferProxyArtifact from '../artifacts/TokenTransferProxy.json'; import * as TokenTransferProxyArtifact from '../src/artifacts/TokenTransferProxy.json';
import * as EtherTokenArtifact from '../artifacts/WETH9.json'; import * as EtherTokenArtifact from '../src/artifacts/WETH9.json';
import * as ZRXArtifact from '../artifacts/ZRXToken.json'; import * as ZRXArtifact from '../src/artifacts/ZRXToken.json';
import { Artifact } from './types'; import { Artifact } from './types';

View File

@ -2,12 +2,14 @@ import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { DummyTokenContract } from '../src/contract_wrappers/generated/dummy_token';
import { BalancesByOwner } from './types'; import { BalancesByOwner } from './types';
export class Balances { export class Balances {
private _tokenContractInstances: Web3.ContractInstance[]; private _tokenContractInstances: DummyTokenContract[];
private _ownerAddresses: string[]; private _ownerAddresses: string[];
constructor(tokenContractInstances: Web3.ContractInstance[], ownerAddresses: string[]) { constructor(tokenContractInstances: DummyTokenContract[], ownerAddresses: string[]) {
this._tokenContractInstances = tokenContractInstances; this._tokenContractInstances = tokenContractInstances;
this._ownerAddresses = ownerAddresses; this._ownerAddresses = ownerAddresses;
} }

View File

@ -3,14 +3,16 @@ import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { ExchangeContract } from '../src/contract_wrappers/generated/exchange';
import { formatters } from './formatters'; import { formatters } from './formatters';
import { Order } from './order'; import { Order } from './order';
export class ExchangeWrapper { export class ExchangeWrapper {
private _exchange: Web3.ContractInstance; private _exchange: ExchangeContract;
private _zeroEx: ZeroEx; private _zeroEx: ZeroEx;
constructor(exchangeContractInstance: Web3.ContractInstance, zeroEx: ZeroEx) { constructor(exchangeContract: ExchangeContract, zeroEx: ZeroEx) {
this._exchange = exchangeContractInstance; this._exchange = exchangeContract;
this._zeroEx = zeroEx; this._zeroEx = zeroEx;
} }
public async fillOrderAsync( public async fillOrderAsync(
@ -23,14 +25,14 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance; const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount); const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
const txHash = await this._exchange.fillOrder( const txHash = await this._exchange.fillOrder.sendTransactionAsync(
params.orderAddresses, params.orderAddresses,
params.orderValues, params.orderValues,
params.fillTakerTokenAmount, params.fillTakerTokenAmount,
params.shouldThrowOnInsufficientBalanceOrAllowance, params.shouldThrowOnInsufficientBalanceOrAllowance,
params.v, params.v as number,
params.r, params.r as string,
params.s, params.s as string,
{ from }, { from },
); );
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash); const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
@ -44,7 +46,7 @@ export class ExchangeWrapper {
opts: { cancelTakerTokenAmount?: BigNumber } = {}, opts: { cancelTakerTokenAmount?: BigNumber } = {},
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const params = order.createCancel(opts.cancelTakerTokenAmount); const params = order.createCancel(opts.cancelTakerTokenAmount);
const txHash = await this._exchange.cancelOrder( const txHash = await this._exchange.cancelOrder.sendTransactionAsync(
params.orderAddresses, params.orderAddresses,
params.orderValues, params.orderValues,
params.cancelTakerTokenAmount, params.cancelTakerTokenAmount,
@ -62,13 +64,13 @@ export class ExchangeWrapper {
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const shouldThrowOnInsufficientBalanceOrAllowance = true; const shouldThrowOnInsufficientBalanceOrAllowance = true;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount); const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
const txHash = await this._exchange.fillOrKillOrder( const txHash = await this._exchange.fillOrKillOrder.sendTransactionAsync(
params.orderAddresses, params.orderAddresses,
params.orderValues, params.orderValues,
params.fillTakerTokenAmount, params.fillTakerTokenAmount,
params.v, params.v as number,
params.r, params.r as string,
params.s, params.s as string,
{ from }, { from },
); );
const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash); const tx = await this._zeroEx.awaitTransactionMinedAsync(txHash);
@ -90,7 +92,7 @@ export class ExchangeWrapper {
shouldThrowOnInsufficientBalanceOrAllowance, shouldThrowOnInsufficientBalanceOrAllowance,
opts.fillTakerTokenAmounts, opts.fillTakerTokenAmounts,
); );
const txHash = await this._exchange.batchFillOrders( const txHash = await this._exchange.batchFillOrders.sendTransactionAsync(
params.orderAddresses, params.orderAddresses,
params.orderValues, params.orderValues,
params.fillTakerTokenAmounts, params.fillTakerTokenAmounts,
@ -116,7 +118,7 @@ export class ExchangeWrapper {
shouldThrowOnInsufficientBalanceOrAllowance, shouldThrowOnInsufficientBalanceOrAllowance,
opts.fillTakerTokenAmounts, opts.fillTakerTokenAmounts,
); );
const txHash = await this._exchange.batchFillOrKillOrders( const txHash = await this._exchange.batchFillOrKillOrders.sendTransactionAsync(
params.orderAddresses, params.orderAddresses,
params.orderValues, params.orderValues,
params.fillTakerTokenAmounts, params.fillTakerTokenAmounts,
@ -141,7 +143,7 @@ export class ExchangeWrapper {
shouldThrowOnInsufficientBalanceOrAllowance, shouldThrowOnInsufficientBalanceOrAllowance,
opts.fillTakerTokenAmount, opts.fillTakerTokenAmount,
); );
const txHash = await this._exchange.fillOrdersUpTo( const txHash = await this._exchange.fillOrdersUpTo.sendTransactionAsync(
params.orderAddresses, params.orderAddresses,
params.orderValues, params.orderValues,
params.fillTakerTokenAmount, params.fillTakerTokenAmount,
@ -162,7 +164,7 @@ export class ExchangeWrapper {
opts: { cancelTakerTokenAmounts?: BigNumber[] } = {}, opts: { cancelTakerTokenAmounts?: BigNumber[] } = {},
): Promise<TransactionReceiptWithDecodedLogs> { ): Promise<TransactionReceiptWithDecodedLogs> {
const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts); const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts);
const txHash = await this._exchange.batchCancelOrders( const txHash = await this._exchange.batchCancelOrders.sendTransactionAsync(
params.orderAddresses, params.orderAddresses,
params.orderValues, params.orderValues,
params.cancelTakerTokenAmounts, params.cancelTakerTokenAmounts,
@ -182,10 +184,10 @@ export class ExchangeWrapper {
public async isValidSignatureAsync(order: Order): Promise<boolean> { public async isValidSignatureAsync(order: Order): Promise<boolean> {
const isValidSignature = await this._exchange.isValidSignature( const isValidSignature = await this._exchange.isValidSignature(
order.params.maker, order.params.maker,
order.params.orderHashHex, order.params.orderHashHex as string,
order.params.v, order.params.v as number,
order.params.r, order.params.r as string,
order.params.s, order.params.s as string,
); );
return isValidSignature; return isValidSignature;
} }

View File

@ -1,12 +1,15 @@
import { BigNumber } from '@0xproject/utils';
import ABI = require('ethereumjs-abi'); import ABI = require('ethereumjs-abi');
import ethUtil = require('ethereumjs-util'); import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { MultiSigWalletContract } from '../src/contract_wrappers/generated/multi_sig_wallet';
import { TransactionDataParams } from './types'; import { TransactionDataParams } from './types';
export class MultiSigWrapper { export class MultiSigWrapper {
private _multiSig: Web3.ContractInstance; private _multiSig: MultiSigWalletContract;
public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) { public static encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) {
const abiEntity = _.find(abi, { name }) as Web3.MethodAbi; const abiEntity = _.find(abi, { name }) as Web3.MethodAbi;
if (_.isUndefined(abiEntity)) { if (_.isUndefined(abiEntity)) {
@ -21,18 +24,18 @@ export class MultiSigWrapper {
}); });
return funcSig + argsData.join(''); return funcSig + argsData.join('');
} }
constructor(multiSigContractInstance: Web3.ContractInstance) { constructor(multiSigContract: MultiSigWalletContract) {
this._multiSig = multiSigContractInstance; this._multiSig = multiSigContract;
} }
public async submitTransactionAsync( public async submitTransactionAsync(
destination: string, destination: string,
from: string, from: string,
dataParams: TransactionDataParams, dataParams: TransactionDataParams,
value: number = 0, value: BigNumber = new BigNumber(0),
) { ) {
const { name, abi, args = [] } = dataParams; const { name, abi, args = [] } = dataParams;
const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args); const encoded = MultiSigWrapper.encodeFnArgs(name, abi, args);
return this._multiSig.submitTransaction(destination, value, encoded, { return this._multiSig.submitTransaction.sendTransactionAsync(destination, value, encoded, {
from, from,
}); });
} }

View File

@ -1,15 +1,17 @@
import * as Web3 from 'web3'; import * as Web3 from 'web3';
import { TokenRegistryContract } from '../src/contract_wrappers/generated/token_registry';
import { Token } from './types'; import { Token } from './types';
export class TokenRegWrapper { export class TokenRegWrapper {
private _tokenReg: Web3.ContractInstance; private _tokenReg: TokenRegistryContract;
constructor(tokenRegContractInstance: Web3.ContractInstance) { constructor(tokenRegContract: TokenRegistryContract) {
this._tokenReg = tokenRegContractInstance; this._tokenReg = tokenRegContract;
} }
public addTokenAsync(token: Token, from: string) { public async addTokenAsync(token: Token, from: string) {
const tx = this._tokenReg.addToken( const tx = this._tokenReg.addToken.sendTransactionAsync(
token.address, token.address as string,
token.name, token.name,
token.symbol, token.symbol,
token.decimals, token.decimals,

View File

@ -44,11 +44,6 @@ export class RequestQueue {
this._processNextRequestFireAndForgetAsync(recipientAddress); this._processNextRequestFireAndForgetAsync(recipientAddress);
}, this._queueIntervalMs); }, this._queueIntervalMs);
} }
protected _stop() {
if (!_.isUndefined(this._queueIntervalId)) {
clearInterval(this._queueIntervalId);
}
}
// tslint:disable-next-line:prefer-function-over-method // tslint:disable-next-line:prefer-function-over-method
protected async _processNextRequestFireAndForgetAsync(recipientAddress: string) { protected async _processNextRequestFireAndForgetAsync(recipientAddress: string) {
throw new Error('Expected processNextRequestFireAndForgetAsync to be implemented by a subclass'); throw new Error('Expected processNextRequestFireAndForgetAsync to be implemented by a subclass');

View File

@ -1,7 +1,8 @@
{ {
"extends": "../../tsconfig", "extends": "../../tsconfig",
"compilerOptions": { "compilerOptions": {
"outDir": "lib" "outDir": "lib",
"strictPropertyInitialization": false
}, },
"include": [ "include": [
"./src/ts/**/*", "./src/ts/**/*",