Fix indentations

This commit is contained in:
Amir Bandeali
2017-11-29 22:26:51 -08:00
parent 4b3e038323
commit e85a69655c
30 changed files with 2636 additions and 2604 deletions

View File

@@ -2,5 +2,5 @@ import {Artifacts} from '../util/artifacts';
const {Migrations} = new Artifacts(artifacts);
module.exports = (deployer: any) => {
deployer.deploy(Migrations);
deployer.deploy(Migrations);
};

View File

@@ -1,43 +1,44 @@
import {Artifacts} from '../util/artifacts';
import {ContractInstance, MultiSigConfigByNetwork} from '../util/types';
const {
MultiSigWalletWithTimeLock,
TokenTransferProxy,
EtherToken,
TokenRegistry,
MultiSigWalletWithTimeLock,
TokenTransferProxy,
EtherToken,
TokenRegistry,
} = new Artifacts(artifacts);
let multiSigConfigByNetwork: MultiSigConfigByNetwork;
try {
/* tslint:disable */
const multiSigConfig = require('./config/multisig');
multiSigConfigByNetwork = multiSigConfig.multiSig;
/* tslint:enable */
/* tslint:disable */
const multiSigConfig = require('./config/multisig');
multiSigConfigByNetwork = multiSigConfig.multiSig;
/* tslint:enable */
} catch (e) {
multiSigConfigByNetwork = {};
multiSigConfigByNetwork = {};
}
module.exports = (deployer: any, network: string, accounts: string[]) => {
const defaultConfig = {
owners: [accounts[0], accounts[1]],
confirmationsRequired: 2,
secondsRequired: 0,
};
const config = multiSigConfigByNetwork[network] || defaultConfig;
if (network !== 'live') {
deployer.deploy(MultiSigWalletWithTimeLock, config.owners, config.confirmationsRequired, config.secondsRequired)
.then(() => {
return deployer.deploy(TokenTransferProxy);
}).then(() => {
return deployer.deploy(TokenRegistry);
}).then(() => {
return deployer.deploy(EtherToken);
});
} else {
deployer.deploy([
[MultiSigWalletWithTimeLock, config.owners, config.confirmationsRequired, config.secondsRequired],
TokenTransferProxy,
TokenRegistry,
]);
}
const defaultConfig = {
owners: [accounts[0], accounts[1]],
confirmationsRequired: 2,
secondsRequired: 0,
};
const config = multiSigConfigByNetwork[network] || defaultConfig;
if (network !== 'live') {
deployer.deploy(MultiSigWalletWithTimeLock, config.owners,
config.confirmationsRequired, config.secondsRequired)
.then(() => {
return deployer.deploy(TokenTransferProxy);
}).then(() => {
return deployer.deploy(TokenRegistry);
}).then(() => {
return deployer.deploy(EtherToken);
});
} else {
deployer.deploy([
[MultiSigWalletWithTimeLock, config.owners, config.confirmationsRequired, config.secondsRequired],
TokenTransferProxy,
TokenRegistry,
]);
}
};

View File

@@ -7,80 +7,80 @@ import {ContractInstance, Token, TokenInfoByNetwork} from '../util/types';
import {tokenInfo} from './config/token_info';
const {
DummyToken,
EtherToken,
ZRXToken,
TokenRegistry,
DummyToken,
EtherToken,
ZRXToken,
TokenRegistry,
} = new Artifacts(artifacts);
module.exports = (deployer: any, network: string) => {
const tokens = network === 'live' ? tokenInfo.live : tokenInfo.development;
deployer.then(() => {
return TokenRegistry.deployed();
}).then((tokenRegistry: ContractInstance) => {
if (network !== 'live') {
const totalSupply = Math.pow(10, 18) * 1000000000;
return Bluebird.each(tokens.map((token: Token) => DummyToken.new(
token.name,
token.symbol,
token.decimals,
totalSupply,
)), _.noop).then((dummyTokens: ContractInstance[]) => {
const weth = {
address: EtherToken.address,
name: 'Ether Token',
symbol: 'WETH',
url: '',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
};
return Bluebird.each(dummyTokens.map((tokenContract: ContractInstance, i: number) => {
const token = tokens[i];
return tokenRegistry.addToken(
tokenContract.address,
token.name,
token.symbol,
token.decimals,
token.ipfsHash,
token.swarmHash,
);
}).concat(tokenRegistry.addToken(
weth.address,
weth.name,
weth.symbol,
weth.decimals,
weth.ipfsHash,
weth.swarmHash,
)), _.noop);
});
} else {
const zrx = {
address: ZRXToken.address,
name: '0x Protocol Token',
symbol: 'ZRX',
url: 'https://www.0xproject.com/',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
};
return Bluebird.each(tokens.map((token: Token) => {
return tokenRegistry.addToken(
token.address,
token.name,
token.symbol,
token.decimals,
token.ipfsHash,
token.swarmHash,
);
}).concat(tokenRegistry.addToken(
zrx.address,
zrx.name,
zrx.symbol,
zrx.decimals,
zrx.ipfsHash,
zrx.swarmHash,
)), _.noop);
}
});
const tokens = network === 'live' ? tokenInfo.live : tokenInfo.development;
deployer.then(() => {
return TokenRegistry.deployed();
}).then((tokenRegistry: ContractInstance) => {
if (network !== 'live') {
const totalSupply = Math.pow(10, 18) * 1000000000;
return Bluebird.each(tokens.map((token: Token) => DummyToken.new(
token.name,
token.symbol,
token.decimals,
totalSupply,
)), _.noop).then((dummyTokens: ContractInstance[]) => {
const weth = {
address: EtherToken.address,
name: 'Ether Token',
symbol: 'WETH',
url: '',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
};
return Bluebird.each(dummyTokens.map((tokenContract: ContractInstance, i: number) => {
const token = tokens[i];
return tokenRegistry.addToken(
tokenContract.address,
token.name,
token.symbol,
token.decimals,
token.ipfsHash,
token.swarmHash,
);
}).concat(tokenRegistry.addToken(
weth.address,
weth.name,
weth.symbol,
weth.decimals,
weth.ipfsHash,
weth.swarmHash,
)), _.noop);
});
} else {
const zrx = {
address: ZRXToken.address,
name: '0x Protocol Token',
symbol: 'ZRX',
url: 'https://www.0xproject.com/',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
};
return Bluebird.each(tokens.map((token: Token) => {
return tokenRegistry.addToken(
token.address,
token.name,
token.symbol,
token.decimals,
token.ipfsHash,
token.swarmHash,
);
}).concat(tokenRegistry.addToken(
zrx.address,
zrx.name,
zrx.symbol,
zrx.decimals,
zrx.ipfsHash,
zrx.swarmHash,
)), _.noop);
}
});
};

View File

@@ -1,27 +1,27 @@
import {Artifacts} from '../util/artifacts';
import {ContractInstance} from '../util/types';
const {
TokenTransferProxy,
Exchange,
TokenRegistry,
TokenTransferProxy,
Exchange,
TokenRegistry,
} = new Artifacts(artifacts);
let tokenTransferProxy: ContractInstance;
module.exports = (deployer: any) => {
deployer.then(async () => {
return Promise.all([
TokenTransferProxy.deployed(),
TokenRegistry.deployed(),
]);
})
.then((instances: ContractInstance[]) => {
let tokenRegistry: ContractInstance;
[tokenTransferProxy, tokenRegistry] = instances;
return tokenRegistry.getTokenAddressBySymbol('ZRX');
})
.then((ptAddress: string) => {
return deployer.deploy(Exchange, ptAddress, tokenTransferProxy.address);
}).then(() => {
return tokenTransferProxy.addAuthorizedAddress(Exchange.address);
});
deployer.then(async () => {
return Promise.all([
TokenTransferProxy.deployed(),
TokenRegistry.deployed(),
]);
})
.then((instances: ContractInstance[]) => {
let tokenRegistry: ContractInstance;
[tokenTransferProxy, tokenRegistry] = instances;
return tokenRegistry.getTokenAddressBySymbol('ZRX');
})
.then((ptAddress: string) => {
return deployer.deploy(Exchange, ptAddress, tokenTransferProxy.address);
}).then(() => {
return tokenTransferProxy.addAuthorizedAddress(Exchange.address);
});
};

View File

@@ -1,25 +1,25 @@
import {Artifacts} from '../util/artifacts';
import {ContractInstance} from '../util/types';
const {
TokenTransferProxy,
MultiSigWalletWithTimeLock,
TokenRegistry,
TokenTransferProxy,
MultiSigWalletWithTimeLock,
TokenRegistry,
} = new Artifacts(artifacts);
let tokenRegistry: ContractInstance;
module.exports = (deployer: any, network: string) => {
if (network !== 'development') {
deployer.then(async () => {
return Promise.all([
TokenTransferProxy.deployed(),
TokenRegistry.deployed(),
]).then((instances: ContractInstance[]) => {
let tokenTransferProxy: ContractInstance;
[tokenTransferProxy, tokenRegistry] = instances;
return tokenTransferProxy.transferOwnership(MultiSigWalletWithTimeLock.address);
}).then(() => {
return tokenRegistry.transferOwnership(MultiSigWalletWithTimeLock.address);
});
});
}
if (network !== 'development') {
deployer.then(async () => {
return Promise.all([
TokenTransferProxy.deployed(),
TokenRegistry.deployed(),
]).then((instances: ContractInstance[]) => {
let tokenTransferProxy: ContractInstance;
[tokenTransferProxy, tokenRegistry] = instances;
return tokenTransferProxy.transferOwnership(MultiSigWalletWithTimeLock.address);
}).then(() => {
return tokenRegistry.transferOwnership(MultiSigWalletWithTimeLock.address);
});
});
}
};

View File

@@ -2,9 +2,9 @@ import {MultiSigConfigByNetwork} from '../../util/types';
// Make a copy of this file named `multisig.js` and input custom params as needed
export const multiSig: MultiSigConfigByNetwork = {
kovan: {
owners: [],
confirmationsRequired: 0,
secondsRequired: 0,
},
kovan: {
owners: [],
confirmationsRequired: 0,
secondsRequired: 0,
},
};

View File

@@ -2,98 +2,98 @@ import {constants} from '../../util/constants';
import {TokenInfoByNetwork} from '../../util/types';
export const tokenInfo: TokenInfoByNetwork = {
development: [
{
name: '0x Protocol Token',
symbol: 'ZRX',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'Augur Reputation Token',
symbol: 'REP',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'Digix DAO Token',
symbol: 'DGD',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'Golem Network Token',
symbol: 'GNT',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'MakerDAO',
symbol: 'MKR',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'Melon Token',
symbol: 'MLN',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
],
live: [
{
address: '0xecf8f87f810ecf450940c9f60066b4a7a501d6a7',
name: 'ETH Wrapper Token',
symbol: 'WETH',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0x48c80f1f4d53d5951e5d5438b54cba84f29f32a5',
name: 'Augur Reputation Token',
symbol: 'REP',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0xe0b7927c4af23765cb51314a0e0521a9645f0e2a',
name: 'Digix DAO Token',
symbol: 'DGD',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0xa74476443119a942de498590fe1f2454d7d4ac0d',
name: 'Golem Network Token',
symbol: 'GNT',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0xc66ea802717bfb9833400264dd12c2bceaa34a6d',
name: 'MakerDAO',
symbol: 'MKR',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0xbeb9ef514a379b997e0798fdcc901ee474b6d9a1',
name: 'Melon Token',
symbol: 'MLN',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
],
development: [
{
name: '0x Protocol Token',
symbol: 'ZRX',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'Augur Reputation Token',
symbol: 'REP',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'Digix DAO Token',
symbol: 'DGD',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'Golem Network Token',
symbol: 'GNT',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'MakerDAO',
symbol: 'MKR',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
name: 'Melon Token',
symbol: 'MLN',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
],
live: [
{
address: '0xecf8f87f810ecf450940c9f60066b4a7a501d6a7',
name: 'ETH Wrapper Token',
symbol: 'WETH',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0x48c80f1f4d53d5951e5d5438b54cba84f29f32a5',
name: 'Augur Reputation Token',
symbol: 'REP',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0xe0b7927c4af23765cb51314a0e0521a9645f0e2a',
name: 'Digix DAO Token',
symbol: 'DGD',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0xa74476443119a942de498590fe1f2454d7d4ac0d',
name: 'Golem Network Token',
symbol: 'GNT',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0xc66ea802717bfb9833400264dd12c2bceaa34a6d',
name: 'MakerDAO',
symbol: 'MKR',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
{
address: '0xbeb9ef514a379b997e0798fdcc901ee474b6d9a1',
name: 'Melon Token',
symbol: 'MLN',
decimals: 18,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
},
],
};

View File

@@ -18,100 +18,101 @@ const expect = chai.expect;
const web3: Web3 = (global as any).web3;
contract('EtherToken', (accounts: string[]) => {
const account = accounts[0];
const gasPrice = ZeroEx.toBaseUnitAmount(new BigNumber(20), 9);
let zeroEx: ZeroEx;
let etherTokenAddress: string;
before(async () => {
etherTokenAddress = EtherToken.address;
zeroEx = new ZeroEx(web3.currentProvider, {
gasPrice,
etherTokenContractAddress: etherTokenAddress,
});
});
const sendTransactionAsync = promisify(web3.eth.sendTransaction);
const getEthBalanceAsync = async (owner: string) => {
const balanceStr = await promisify(web3.eth.getBalance)(owner);
const balance = new BigNumber(balanceStr);
return balance;
};
describe('deposit', () => {
it('should throw if caller attempts to deposit more Ether than caller balance', async () => {
const initEthBalance = await getEthBalanceAsync(account);
const ethToDeposit = initEthBalance.plus(1);
return expect(zeroEx.etherToken.depositAsync(ethToDeposit, account))
.to.be.rejectedWith(ZeroExError.InsufficientEthBalanceForDeposit);
const account = accounts[0];
const gasPrice = ZeroEx.toBaseUnitAmount(new BigNumber(20), 9);
let zeroEx: ZeroEx;
let etherTokenAddress: string;
before(async () => {
etherTokenAddress = EtherToken.address;
zeroEx = new ZeroEx(web3.currentProvider, {
gasPrice,
etherTokenContractAddress: etherTokenAddress,
});
});
it('should convert deposited Ether to wrapped Ether tokens', async () => {
const initEthBalance = await getEthBalanceAsync(account);
const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
const sendTransactionAsync = promisify(web3.eth.sendTransaction);
const getEthBalanceAsync = async (owner: string) => {
const balanceStr = await promisify(web3.eth.getBalance)(owner);
const balance = new BigNumber(balanceStr);
return balance;
};
const ethToDeposit = new BigNumber(web3.toWei(1, 'ether'));
describe('deposit', () => {
it('should throw if caller attempts to deposit more Ether than caller balance', async () => {
const initEthBalance = await getEthBalanceAsync(account);
const ethToDeposit = initEthBalance.plus(1);
const txHash = await zeroEx.etherToken.depositAsync(ethToDeposit, account);
const receipt = await zeroEx.awaitTransactionMinedAsync(txHash);
return expect(zeroEx.etherToken.depositAsync(ethToDeposit, account))
.to.be.rejectedWith(ZeroExError.InsufficientEthBalanceForDeposit);
});
const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
const finalEthBalance = await getEthBalanceAsync(account);
const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
it('should convert deposited Ether to wrapped Ether tokens', async () => {
const initEthBalance = await getEthBalanceAsync(account);
const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas)));
expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit));
});
});
const ethToDeposit = new BigNumber(web3.toWei(1, 'ether'));
describe('withdraw', () => {
it('should throw if caller attempts to withdraw greater than caller balance', async () => {
const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
const ethTokensToWithdraw = initEthTokenBalance.plus(1);
const txHash = await zeroEx.etherToken.depositAsync(ethToDeposit, account);
const receipt = await zeroEx.awaitTransactionMinedAsync(txHash);
return expect(zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account))
.to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal);
const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
const finalEthBalance = await getEthBalanceAsync(account);
const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas)));
expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit));
});
});
it('should convert ether tokens to ether with sufficient balance', async () => {
const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
const initEthBalance = await getEthBalanceAsync(account);
const ethTokensToWithdraw = initEthTokenBalance;
expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0);
const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account);
const receipt = await zeroEx.awaitTransactionMinedAsync(txHash);
describe('withdraw', () => {
it('should throw if caller attempts to withdraw greater than caller balance', async () => {
const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
const ethTokensToWithdraw = initEthTokenBalance.plus(1);
const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
const finalEthBalance = await getEthBalanceAsync(account);
const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
return expect(zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account))
.to.be.rejectedWith(ZeroExError.InsufficientWEthBalanceForWithdrawal);
});
expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.plus(ethTokensToWithdraw.minus(ethSpentOnGas)));
expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.minus(ethTokensToWithdraw));
it('should convert ether tokens to ether with sufficient balance', async () => {
const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
const initEthBalance = await getEthBalanceAsync(account);
const ethTokensToWithdraw = initEthTokenBalance;
expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0);
const txHash = await zeroEx.etherToken.withdrawAsync(ethTokensToWithdraw, account);
const receipt = await zeroEx.awaitTransactionMinedAsync(txHash);
const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
const finalEthBalance = await getEthBalanceAsync(account);
const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
expect(finalEthBalance).to.be.bignumber
.equal(initEthBalance.plus(ethTokensToWithdraw.minus(ethSpentOnGas)));
expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.minus(ethTokensToWithdraw));
});
});
});
describe('fallback', () => {
it('should convert sent ether to ether tokens', async () => {
const initEthBalance = await getEthBalanceAsync(account);
const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
describe('fallback', () => {
it('should convert sent ether to ether tokens', async () => {
const initEthBalance = await getEthBalanceAsync(account);
const initEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
const ethToDeposit = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
const ethToDeposit = ZeroEx.toBaseUnitAmount(new BigNumber(1), 18);
const txHash = await sendTransactionAsync({
from: account,
to: etherTokenAddress,
value: ethToDeposit,
gasPrice,
});
const txHash = await sendTransactionAsync({
from: account,
to: etherTokenAddress,
value: ethToDeposit,
gasPrice,
});
const receipt = await zeroEx.awaitTransactionMinedAsync(txHash);
const receipt = await zeroEx.awaitTransactionMinedAsync(txHash);
const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
const finalEthBalance = await getEthBalanceAsync(account);
const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
const finalEthBalance = await getEthBalanceAsync(account);
const finalEthTokenBalance = await zeroEx.token.getBalanceAsync(etherTokenAddress, account);
expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas)));
expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit));
expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas)));
expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit));
});
});
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -13,161 +13,161 @@ chaiSetup.configure();
const expect = chai.expect;
const {
Exchange,
TokenRegistry,
Exchange,
TokenRegistry,
} = new Artifacts(artifacts);
contract('Exchange', (accounts: string[]) => {
const maker = accounts[0];
const feeRecipient = accounts[1] || accounts[accounts.length - 1];
const maker = accounts[0];
const feeRecipient = accounts[1] || accounts[accounts.length - 1];
let order: Order;
let exchangeWrapper: ExchangeWrapper;
let orderFactory: OrderFactory;
let order: Order;
let exchangeWrapper: ExchangeWrapper;
let orderFactory: OrderFactory;
before(async () => {
const [tokenRegistry, exchange] = await Promise.all([
TokenRegistry.deployed(),
Exchange.deployed(),
]);
exchangeWrapper = new ExchangeWrapper(exchange);
const [repAddress, dgdAddress] = await Promise.all([
tokenRegistry.getTokenAddressBySymbol('REP'),
tokenRegistry.getTokenAddressBySymbol('DGD'),
]);
const defaultOrderParams = {
exchangeContractAddress: Exchange.address,
maker,
feeRecipient,
makerToken: repAddress,
takerToken: dgdAddress,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
};
orderFactory = new OrderFactory(defaultOrderParams);
});
beforeEach(async () => {
order = await orderFactory.newSignedOrderAsync();
});
describe('getOrderHash', () => {
it('should output the correct orderHash', async () => {
const orderHashHex = await exchangeWrapper.getOrderHashAsync(order);
expect(order.params.orderHashHex).to.be.equal(orderHashHex);
before(async () => {
const [tokenRegistry, exchange] = await Promise.all([
TokenRegistry.deployed(),
Exchange.deployed(),
]);
exchangeWrapper = new ExchangeWrapper(exchange);
const [repAddress, dgdAddress] = await Promise.all([
tokenRegistry.getTokenAddressBySymbol('REP'),
tokenRegistry.getTokenAddressBySymbol('DGD'),
]);
const defaultOrderParams = {
exchangeContractAddress: Exchange.address,
maker,
feeRecipient,
makerToken: repAddress,
takerToken: dgdAddress,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
};
orderFactory = new OrderFactory(defaultOrderParams);
});
});
describe('isValidSignature', () => {
beforeEach(async () => {
order = await orderFactory.newSignedOrderAsync();
order = await orderFactory.newSignedOrderAsync();
});
it('should return true with a valid signature', async () => {
const success = await exchangeWrapper.isValidSignatureAsync(order);
const isValidSignature = order.isValidSignature();
expect(isValidSignature).to.be.true();
expect(success).to.be.true();
describe('getOrderHash', () => {
it('should output the correct orderHash', async () => {
const orderHashHex = await exchangeWrapper.getOrderHashAsync(order);
expect(order.params.orderHashHex).to.be.equal(orderHashHex);
});
});
it('should return false with an invalid signature', async () => {
order.params.r = ethUtil.bufferToHex(ethUtil.sha3('invalidR'));
order.params.s = ethUtil.bufferToHex(ethUtil.sha3('invalidS'));
const success = await exchangeWrapper.isValidSignatureAsync(order);
expect(order.isValidSignature()).to.be.false();
expect(success).to.be.false();
});
});
describe('isValidSignature', () => {
beforeEach(async () => {
order = await orderFactory.newSignedOrderAsync();
});
describe('isRoundingError', () => {
it('should return false if there is a rounding error of 0.1%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(999);
const target = new BigNumber(50);
// rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.false();
it('should return true with a valid signature', async () => {
const success = await exchangeWrapper.isValidSignatureAsync(order);
const isValidSignature = order.isValidSignature();
expect(isValidSignature).to.be.true();
expect(success).to.be.true();
});
it('should return false with an invalid signature', async () => {
order.params.r = ethUtil.bufferToHex(ethUtil.sha3('invalidR'));
order.params.s = ethUtil.bufferToHex(ethUtil.sha3('invalidS'));
const success = await exchangeWrapper.isValidSignatureAsync(order);
expect(order.isValidSignature()).to.be.false();
expect(success).to.be.false();
});
});
it('should return false if there is a rounding of 0.09%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(9991);
const target = new BigNumber(500);
// rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.false();
describe('isRoundingError', () => {
it('should return false if there is a rounding error of 0.1%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(999);
const target = new BigNumber(50);
// rounding error = ((20*50/999) - floor(20*50/999)) / (20*50/999) = 0.1%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
it('should return false if there is a rounding of 0.09%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(9991);
const target = new BigNumber(500);
// rounding error = ((20*500/9991) - floor(20*500/9991)) / (20*500/9991) = 0.09%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
it('should return true if there is a rounding error of 0.11%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(9989);
const target = new BigNumber(500);
// rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.true();
});
it('should return true if there is a rounding error > 0.1%', async () => {
const numerator = new BigNumber(3);
const denominator = new BigNumber(7);
const target = new BigNumber(10);
// rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.true();
});
it('should return false when there is no rounding error', async () => {
const numerator = new BigNumber(1);
const denominator = new BigNumber(2);
const target = new BigNumber(10);
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
it('should return false when there is rounding error <= 0.1%', async () => {
// randomly generated numbers
const numerator = new BigNumber(76564);
const denominator = new BigNumber(676373677);
const target = new BigNumber(105762562);
// rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) /
// (76564*105762562/676373677) = 0.0007%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
});
it('should return true if there is a rounding error of 0.11%', async () => {
const numerator = new BigNumber(20);
const denominator = new BigNumber(9989);
const target = new BigNumber(500);
// rounding error = ((20*500/9989) - floor(20*500/9989)) / (20*500/9989) = 0.011%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.true();
describe('getPartialAmount', () => {
it('should return the numerator/denominator*target', async () => {
const numerator = new BigNumber(1);
const denominator = new BigNumber(2);
const target = new BigNumber(10);
const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
const expectedPartialAmount = 5;
expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
});
it('should round down', async () => {
const numerator = new BigNumber(2);
const denominator = new BigNumber(3);
const target = new BigNumber(10);
const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
const expectedPartialAmount = 6;
expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
});
it('should round .5 down', async () => {
const numerator = new BigNumber(1);
const denominator = new BigNumber(20);
const target = new BigNumber(10);
const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
const expectedPartialAmount = 0;
expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
});
});
it('should return true if there is a rounding error > 0.1%', async () => {
const numerator = new BigNumber(3);
const denominator = new BigNumber(7);
const target = new BigNumber(10);
// rounding error = ((3*10/7) - floor(3*10/7)) / (3*10/7) = 6.67%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.true();
});
it('should return false when there is no rounding error', async () => {
const numerator = new BigNumber(1);
const denominator = new BigNumber(2);
const target = new BigNumber(10);
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
it('should return false when there is rounding error <= 0.1%', async () => {
// randomly generated numbers
const numerator = new BigNumber(76564);
const denominator = new BigNumber(676373677);
const target = new BigNumber(105762562);
// rounding error = ((76564*105762562/676373677) - floor(76564*105762562/676373677)) /
// (76564*105762562/676373677) = 0.0007%
const isRoundingError = await exchangeWrapper.isRoundingErrorAsync(numerator, denominator, target);
expect(isRoundingError).to.be.false();
});
});
describe('getPartialAmount', () => {
it('should return the numerator/denominator*target', async () => {
const numerator = new BigNumber(1);
const denominator = new BigNumber(2);
const target = new BigNumber(10);
const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
const expectedPartialAmount = 5;
expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
});
it('should round down', async () => {
const numerator = new BigNumber(2);
const denominator = new BigNumber(3);
const target = new BigNumber(10);
const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
const expectedPartialAmount = 6;
expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
});
it('should round .5 down', async () => {
const numerator = new BigNumber(1);
const denominator = new BigNumber(20);
const target = new BigNumber(10);
const partialAmount = await exchangeWrapper.getPartialAmountAsync(numerator, denominator, target);
const expectedPartialAmount = 0;
expect(partialAmount).to.be.bignumber.equal(expectedPartialAmount);
});
});
});

View File

@@ -15,303 +15,307 @@ import {chaiSetup} from '../utils/chai_setup';
chaiSetup.configure();
const expect = chai.expect;
const {
Exchange,
TokenTransferProxy,
DummyToken,
TokenRegistry,
Exchange,
TokenTransferProxy,
DummyToken,
TokenRegistry,
} = new Artifacts(artifacts);
contract('Exchange', (accounts: string[]) => {
const maker = accounts[0];
const tokenOwner = accounts[0];
const taker = accounts[1] || accounts[accounts.length - 1];
const feeRecipient = accounts[2] || accounts[accounts.length - 1];
const maker = accounts[0];
const tokenOwner = accounts[0];
const taker = accounts[1] || accounts[accounts.length - 1];
const feeRecipient = accounts[2] || accounts[accounts.length - 1];
const INIT_BAL = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
const INIT_ALLOW = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
const INIT_BAL = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
const INIT_ALLOW = ZeroEx.toBaseUnitAmount(new BigNumber(10000), 18);
let rep: ContractInstance;
let dgd: ContractInstance;
let zrx: ContractInstance;
let exchange: ContractInstance;
let tokenRegistry: ContractInstance;
let rep: ContractInstance;
let dgd: ContractInstance;
let zrx: ContractInstance;
let exchange: ContractInstance;
let tokenRegistry: ContractInstance;
let balances: BalancesByOwner;
let balances: BalancesByOwner;
let exWrapper: ExchangeWrapper;
let dmyBalances: Balances;
let orderFactory: OrderFactory;
let exWrapper: ExchangeWrapper;
let dmyBalances: Balances;
let orderFactory: OrderFactory;
before(async () => {
[tokenRegistry, exchange] = await Promise.all([
TokenRegistry.deployed(),
Exchange.deployed(),
]);
exWrapper = new ExchangeWrapper(exchange);
const [repAddress, dgdAddress, zrxAddress] = await Promise.all([
tokenRegistry.getTokenAddressBySymbol('REP'),
tokenRegistry.getTokenAddressBySymbol('DGD'),
tokenRegistry.getTokenAddressBySymbol('ZRX'),
]);
const defaultOrderParams = {
exchangeContractAddress: Exchange.address,
maker,
feeRecipient,
makerToken: repAddress,
takerToken: dgdAddress,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
};
orderFactory = new OrderFactory(defaultOrderParams);
[rep, dgd, zrx] = await Promise.all([
DummyToken.at(repAddress),
DummyToken.at(dgdAddress),
DummyToken.at(zrxAddress),
]);
dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]);
await Promise.all([
rep.approve(TokenTransferProxy.address, INIT_ALLOW, {from: maker}),
rep.approve(TokenTransferProxy.address, INIT_ALLOW, {from: taker}),
rep.setBalance(maker, INIT_BAL, {from: tokenOwner}),
rep.setBalance(taker, INIT_BAL, {from: tokenOwner}),
dgd.approve(TokenTransferProxy.address, INIT_ALLOW, {from: maker}),
dgd.approve(TokenTransferProxy.address, INIT_ALLOW, {from: taker}),
dgd.setBalance(maker, INIT_BAL, {from: tokenOwner}),
dgd.setBalance(taker, INIT_BAL, {from: tokenOwner}),
zrx.approve(TokenTransferProxy.address, INIT_ALLOW, {from: maker}),
zrx.approve(TokenTransferProxy.address, INIT_ALLOW, {from: taker}),
zrx.setBalance(maker, INIT_BAL, {from: tokenOwner}),
zrx.setBalance(taker, INIT_BAL, {from: tokenOwner}),
]);
});
describe('fillOrKillOrder', () => {
beforeEach(async () => {
balances = await dmyBalances.getAsync();
});
it('should transfer the correct amounts', async () => {
const order = await orderFactory.newSignedOrderAsync({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
});
const fillTakerTokenAmount = order.params.takerTokenAmount.div(2);
await exWrapper.fillOrKillOrderAsync(order, taker, {fillTakerTokenAmount});
const newBalances = await dmyBalances.getAsync();
const fillMakerTokenAmount = fillTakerTokenAmount
.times(order.params.makerTokenAmount)
.dividedToIntegerBy(order.params.takerTokenAmount);
const makerFee = order.params.makerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
const takerFee = order.params.takerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
expect(newBalances[maker][order.params.makerToken])
.to.be.bignumber.equal(balances[maker][order.params.makerToken].minus(fillMakerTokenAmount));
expect(newBalances[maker][order.params.takerToken])
.to.be.bignumber.equal(balances[maker][order.params.takerToken].add(fillTakerTokenAmount));
expect(newBalances[maker][zrx.address]).to.be.bignumber.equal(balances[maker][zrx.address].minus(makerFee));
expect(newBalances[taker][order.params.takerToken])
.to.be.bignumber.equal(balances[taker][order.params.takerToken].minus(fillTakerTokenAmount));
expect(newBalances[taker][order.params.makerToken])
.to.be.bignumber.equal(balances[taker][order.params.makerToken].add(fillMakerTokenAmount));
expect(newBalances[taker][zrx.address]).to.be.bignumber.equal(balances[taker][zrx.address].minus(takerFee));
expect(newBalances[feeRecipient][zrx.address])
.to.be.bignumber.equal(balances[feeRecipient][zrx.address].add(makerFee.add(takerFee)));
});
it('should throw if an order is expired', async () => {
const order = await orderFactory.newSignedOrderAsync({
expirationTimestampInSec: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
});
return expect(exWrapper.fillOrKillOrderAsync(order, taker))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if entire fillTakerTokenAmount not filled', async () => {
const order = await orderFactory.newSignedOrderAsync();
const from = taker;
await exWrapper.fillOrderAsync(order, from, {fillTakerTokenAmount: order.params.takerTokenAmount.div(2)});
return expect(exWrapper.fillOrKillOrderAsync(order, taker))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('batch functions', () => {
let orders: Order[];
beforeEach(async () => {
orders = await Promise.all([
orderFactory.newSignedOrderAsync(),
orderFactory.newSignedOrderAsync(),
orderFactory.newSignedOrderAsync(),
]);
balances = await dmyBalances.getAsync();
});
describe('batchFillOrders', () => {
it('should transfer the correct amounts', async () => {
const fillTakerTokenAmounts: BigNumber[] = [];
const makerToken = rep.address;
const takerToken = dgd.address;
orders.forEach(order => {
const fillTakerTokenAmount = order.params.takerTokenAmount.div(2);
const fillMakerTokenAmount = fillTakerTokenAmount
.times(order.params.makerTokenAmount)
.dividedToIntegerBy(order.params.takerTokenAmount);
const makerFee = order.params.makerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
const takerFee = order.params.takerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
fillTakerTokenAmounts.push(fillTakerTokenAmount);
balances[maker][makerToken] = balances[maker][makerToken].minus(fillMakerTokenAmount);
balances[maker][takerToken] = balances[maker][takerToken].add(fillTakerTokenAmount);
balances[maker][zrx.address] = balances[maker][zrx.address].minus(makerFee);
balances[taker][makerToken] = balances[taker][makerToken].add(fillMakerTokenAmount);
balances[taker][takerToken] = balances[taker][takerToken].minus(fillTakerTokenAmount);
balances[taker][zrx.address] = balances[taker][zrx.address].minus(takerFee);
balances[feeRecipient][zrx.address] = balances[feeRecipient][zrx.address].add(makerFee.add(takerFee));
});
await exWrapper.batchFillOrdersAsync(orders, taker, {fillTakerTokenAmounts});
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
});
describe('batchFillOrKillOrders', () => {
it('should transfer the correct amounts', async () => {
const fillTakerTokenAmounts: BigNumber[] = [];
const makerToken = rep.address;
const takerToken = dgd.address;
orders.forEach(order => {
const fillTakerTokenAmount = order.params.takerTokenAmount.div(2);
const fillMakerTokenAmount = fillTakerTokenAmount
.times(order.params.makerTokenAmount)
.dividedToIntegerBy(order.params.takerTokenAmount);
const makerFee = order.params.makerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
const takerFee = order.params.takerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
fillTakerTokenAmounts.push(fillTakerTokenAmount);
balances[maker][makerToken] = balances[maker][makerToken].minus(fillMakerTokenAmount);
balances[maker][takerToken] = balances[maker][takerToken].add(fillTakerTokenAmount);
balances[maker][zrx.address] = balances[maker][zrx.address].minus(makerFee);
balances[taker][makerToken] = balances[taker][makerToken].add(fillMakerTokenAmount);
balances[taker][takerToken] = balances[taker][takerToken].minus(fillTakerTokenAmount);
balances[taker][zrx.address] = balances[taker][zrx.address].minus(takerFee);
balances[feeRecipient][zrx.address] = balances[feeRecipient][zrx.address].add(makerFee.add(takerFee));
});
await exWrapper.batchFillOrKillOrdersAsync(orders, taker, {fillTakerTokenAmounts});
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
it('should throw if a single order does not fill the expected amount', async () => {
const fillTakerTokenAmounts: BigNumber[] = [];
const makerToken = rep.address;
const takerToken = dgd.address;
orders.forEach(order => {
const fillTakerTokenAmount = order.params.takerTokenAmount.div(2);
fillTakerTokenAmounts.push(fillTakerTokenAmount);
});
await exWrapper.fillOrKillOrderAsync(orders[0], taker);
return expect(exWrapper.batchFillOrKillOrdersAsync(orders, taker, {fillTakerTokenAmounts}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('fillOrdersUpTo', () => {
it('should stop when the entire fillTakerTokenAmount is filled', async () => {
const fillTakerTokenAmount = orders[0].params.takerTokenAmount.plus(orders[1].params.takerTokenAmount.div(2));
await exWrapper.fillOrdersUpToAsync(orders, taker, {fillTakerTokenAmount});
const newBalances = await dmyBalances.getAsync();
const fillMakerTokenAmount = orders[0].params.makerTokenAmount.add(
orders[1].params.makerTokenAmount.dividedToIntegerBy(2));
const makerFee = orders[0].params.makerFee.add(orders[1].params.makerFee.dividedToIntegerBy(2));
const takerFee = orders[0].params.takerFee.add(orders[1].params.takerFee.dividedToIntegerBy(2));
expect(newBalances[maker][orders[0].params.makerToken])
.to.be.bignumber.equal(balances[maker][orders[0].params.makerToken].minus(fillMakerTokenAmount));
expect(newBalances[maker][orders[0].params.takerToken])
.to.be.bignumber.equal(balances[maker][orders[0].params.takerToken].add(fillTakerTokenAmount));
expect(newBalances[maker][zrx.address]).to.be.bignumber.equal(balances[maker][zrx.address].minus(makerFee));
expect(newBalances[taker][orders[0].params.takerToken])
.to.be.bignumber.equal(balances[taker][orders[0].params.takerToken].minus(fillTakerTokenAmount));
expect(newBalances[taker][orders[0].params.makerToken])
.to.be.bignumber.equal(balances[taker][orders[0].params.makerToken].add(fillMakerTokenAmount));
expect(newBalances[taker][zrx.address]).to.be.bignumber.equal(balances[taker][zrx.address].minus(takerFee));
expect(newBalances[feeRecipient][zrx.address])
.to.be.bignumber.equal(balances[feeRecipient][zrx.address].add(makerFee.add(takerFee)));
});
it('should fill all orders if cannot fill entire fillTakerTokenAmount', async () => {
const fillTakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18);
orders.forEach(order => {
balances[maker][order.params.makerToken] = balances[maker][order.params.makerToken]
.minus(order.params.makerTokenAmount);
balances[maker][order.params.takerToken] = balances[maker][order.params.takerToken]
.add(order.params.takerTokenAmount);
balances[maker][zrx.address] = balances[maker][zrx.address]
.minus(order.params.makerFee);
balances[taker][order.params.makerToken] = balances[taker][order.params.makerToken]
.add(order.params.makerTokenAmount);
balances[taker][order.params.takerToken] = balances[taker][order.params.takerToken]
.minus(order.params.takerTokenAmount);
balances[taker][zrx.address] = balances[taker][zrx.address].minus(order.params.takerFee);
balances[feeRecipient][zrx.address] = balances[feeRecipient][zrx.address]
.add(order.params.makerFee
.add(order.params.takerFee));
});
await exWrapper.fillOrdersUpToAsync(orders, taker, {fillTakerTokenAmount});
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
it('should throw when an order does not use the same takerToken', async () => {
orders = await Promise.all([
orderFactory.newSignedOrderAsync(),
orderFactory.newSignedOrderAsync({takerToken: zrx.address}),
orderFactory.newSignedOrderAsync(),
before(async () => {
[tokenRegistry, exchange] = await Promise.all([
TokenRegistry.deployed(),
Exchange.deployed(),
]);
exWrapper = new ExchangeWrapper(exchange);
const [repAddress, dgdAddress, zrxAddress] = await Promise.all([
tokenRegistry.getTokenAddressBySymbol('REP'),
tokenRegistry.getTokenAddressBySymbol('DGD'),
tokenRegistry.getTokenAddressBySymbol('ZRX'),
]);
return expect(
exWrapper.fillOrdersUpToAsync(
orders, taker, {fillTakerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18)}),
).to.be.rejectedWith(constants.INVALID_OPCODE);
});
const defaultOrderParams = {
exchangeContractAddress: Exchange.address,
maker,
feeRecipient,
makerToken: repAddress,
takerToken: dgdAddress,
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
makerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
takerFee: ZeroEx.toBaseUnitAmount(new BigNumber(1), 18),
};
orderFactory = new OrderFactory(defaultOrderParams);
[rep, dgd, zrx] = await Promise.all([
DummyToken.at(repAddress),
DummyToken.at(dgdAddress),
DummyToken.at(zrxAddress),
]);
dmyBalances = new Balances([rep, dgd, zrx], [maker, taker, feeRecipient]);
await Promise.all([
rep.approve(TokenTransferProxy.address, INIT_ALLOW, {from: maker}),
rep.approve(TokenTransferProxy.address, INIT_ALLOW, {from: taker}),
rep.setBalance(maker, INIT_BAL, {from: tokenOwner}),
rep.setBalance(taker, INIT_BAL, {from: tokenOwner}),
dgd.approve(TokenTransferProxy.address, INIT_ALLOW, {from: maker}),
dgd.approve(TokenTransferProxy.address, INIT_ALLOW, {from: taker}),
dgd.setBalance(maker, INIT_BAL, {from: tokenOwner}),
dgd.setBalance(taker, INIT_BAL, {from: tokenOwner}),
zrx.approve(TokenTransferProxy.address, INIT_ALLOW, {from: maker}),
zrx.approve(TokenTransferProxy.address, INIT_ALLOW, {from: taker}),
zrx.setBalance(maker, INIT_BAL, {from: tokenOwner}),
zrx.setBalance(taker, INIT_BAL, {from: tokenOwner}),
]);
});
describe('batchCancelOrders', () => {
it('should be able to cancel multiple orders', async () => {
const cancelTakerTokenAmounts = _.map(orders, order => order.params.takerTokenAmount);
await exWrapper.batchCancelOrdersAsync(orders, maker, {cancelTakerTokenAmounts});
describe('fillOrKillOrder', () => {
beforeEach(async () => {
balances = await dmyBalances.getAsync();
});
const res = await exWrapper.batchFillOrdersAsync(
orders, taker, {fillTakerTokenAmounts: cancelTakerTokenAmounts});
const newBalances = await dmyBalances.getAsync();
expect(balances).to.be.deep.equal(newBalances);
});
it('should transfer the correct amounts', async () => {
const order = await orderFactory.newSignedOrderAsync({
makerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(100), 18),
takerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(200), 18),
});
const fillTakerTokenAmount = order.params.takerTokenAmount.div(2);
await exWrapper.fillOrKillOrderAsync(order, taker, {fillTakerTokenAmount});
const newBalances = await dmyBalances.getAsync();
const fillMakerTokenAmount = fillTakerTokenAmount
.times(order.params.makerTokenAmount)
.dividedToIntegerBy(order.params.takerTokenAmount);
const makerFee = order.params.makerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
const takerFee = order.params.takerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
expect(newBalances[maker][order.params.makerToken])
.to.be.bignumber.equal(balances[maker][order.params.makerToken].minus(fillMakerTokenAmount));
expect(newBalances[maker][order.params.takerToken])
.to.be.bignumber.equal(balances[maker][order.params.takerToken].add(fillTakerTokenAmount));
expect(newBalances[maker][zrx.address]).to.be.bignumber.equal(balances[maker][zrx.address].minus(makerFee));
expect(newBalances[taker][order.params.takerToken])
.to.be.bignumber.equal(balances[taker][order.params.takerToken].minus(fillTakerTokenAmount));
expect(newBalances[taker][order.params.makerToken])
.to.be.bignumber.equal(balances[taker][order.params.makerToken].add(fillMakerTokenAmount));
expect(newBalances[taker][zrx.address]).to.be.bignumber.equal(balances[taker][zrx.address].minus(takerFee));
expect(newBalances[feeRecipient][zrx.address])
.to.be.bignumber.equal(balances[feeRecipient][zrx.address].add(makerFee.add(takerFee)));
});
it('should throw if an order is expired', async () => {
const order = await orderFactory.newSignedOrderAsync({
expirationTimestampInSec: new BigNumber(Math.floor((Date.now() - 10000) / 1000)),
});
return expect(exWrapper.fillOrKillOrderAsync(order, taker))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if entire fillTakerTokenAmount not filled', async () => {
const order = await orderFactory.newSignedOrderAsync();
const from = taker;
await exWrapper.fillOrderAsync(order, from, {fillTakerTokenAmount: order.params.takerTokenAmount.div(2)});
return expect(exWrapper.fillOrKillOrderAsync(order, taker))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('batch functions', () => {
let orders: Order[];
beforeEach(async () => {
orders = await Promise.all([
orderFactory.newSignedOrderAsync(),
orderFactory.newSignedOrderAsync(),
orderFactory.newSignedOrderAsync(),
]);
balances = await dmyBalances.getAsync();
});
describe('batchFillOrders', () => {
it('should transfer the correct amounts', async () => {
const fillTakerTokenAmounts: BigNumber[] = [];
const makerToken = rep.address;
const takerToken = dgd.address;
orders.forEach(order => {
const fillTakerTokenAmount = order.params.takerTokenAmount.div(2);
const fillMakerTokenAmount = fillTakerTokenAmount
.times(order.params.makerTokenAmount)
.dividedToIntegerBy(order.params.takerTokenAmount);
const makerFee = order.params.makerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
const takerFee = order.params.takerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
fillTakerTokenAmounts.push(fillTakerTokenAmount);
balances[maker][makerToken] = balances[maker][makerToken].minus(fillMakerTokenAmount);
balances[maker][takerToken] = balances[maker][takerToken].add(fillTakerTokenAmount);
balances[maker][zrx.address] = balances[maker][zrx.address].minus(makerFee);
balances[taker][makerToken] = balances[taker][makerToken].add(fillMakerTokenAmount);
balances[taker][takerToken] = balances[taker][takerToken].minus(fillTakerTokenAmount);
balances[taker][zrx.address] = balances[taker][zrx.address].minus(takerFee);
balances[feeRecipient][zrx.address] =
balances[feeRecipient][zrx.address].add(makerFee.add(takerFee));
});
await exWrapper.batchFillOrdersAsync(orders, taker, {fillTakerTokenAmounts});
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
});
describe('batchFillOrKillOrders', () => {
it('should transfer the correct amounts', async () => {
const fillTakerTokenAmounts: BigNumber[] = [];
const makerToken = rep.address;
const takerToken = dgd.address;
orders.forEach(order => {
const fillTakerTokenAmount = order.params.takerTokenAmount.div(2);
const fillMakerTokenAmount = fillTakerTokenAmount
.times(order.params.makerTokenAmount)
.dividedToIntegerBy(order.params.takerTokenAmount);
const makerFee = order.params.makerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
const takerFee = order.params.takerFee
.times(fillMakerTokenAmount)
.dividedToIntegerBy(order.params.makerTokenAmount);
fillTakerTokenAmounts.push(fillTakerTokenAmount);
balances[maker][makerToken] = balances[maker][makerToken].minus(fillMakerTokenAmount);
balances[maker][takerToken] = balances[maker][takerToken].add(fillTakerTokenAmount);
balances[maker][zrx.address] = balances[maker][zrx.address].minus(makerFee);
balances[taker][makerToken] = balances[taker][makerToken].add(fillMakerTokenAmount);
balances[taker][takerToken] = balances[taker][takerToken].minus(fillTakerTokenAmount);
balances[taker][zrx.address] = balances[taker][zrx.address].minus(takerFee);
balances[feeRecipient][zrx.address] =
balances[feeRecipient][zrx.address].add(makerFee.add(takerFee));
});
await exWrapper.batchFillOrKillOrdersAsync(orders, taker, {fillTakerTokenAmounts});
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
it('should throw if a single order does not fill the expected amount', async () => {
const fillTakerTokenAmounts: BigNumber[] = [];
const makerToken = rep.address;
const takerToken = dgd.address;
orders.forEach(order => {
const fillTakerTokenAmount = order.params.takerTokenAmount.div(2);
fillTakerTokenAmounts.push(fillTakerTokenAmount);
});
await exWrapper.fillOrKillOrderAsync(orders[0], taker);
return expect(exWrapper.batchFillOrKillOrdersAsync(orders, taker, {fillTakerTokenAmounts}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('fillOrdersUpTo', () => {
it('should stop when the entire fillTakerTokenAmount is filled', async () => {
const fillTakerTokenAmount =
orders[0].params.takerTokenAmount.plus(orders[1].params.takerTokenAmount.div(2));
await exWrapper.fillOrdersUpToAsync(orders, taker, {fillTakerTokenAmount});
const newBalances = await dmyBalances.getAsync();
const fillMakerTokenAmount = orders[0].params.makerTokenAmount.add(
orders[1].params.makerTokenAmount.dividedToIntegerBy(2));
const makerFee = orders[0].params.makerFee.add(orders[1].params.makerFee.dividedToIntegerBy(2));
const takerFee = orders[0].params.takerFee.add(orders[1].params.takerFee.dividedToIntegerBy(2));
expect(newBalances[maker][orders[0].params.makerToken])
.to.be.bignumber.equal(balances[maker][orders[0].params.makerToken].minus(fillMakerTokenAmount));
expect(newBalances[maker][orders[0].params.takerToken])
.to.be.bignumber.equal(balances[maker][orders[0].params.takerToken].add(fillTakerTokenAmount));
expect(newBalances[maker][zrx.address]).to.be.bignumber
.equal(balances[maker][zrx.address].minus(makerFee));
expect(newBalances[taker][orders[0].params.takerToken])
.to.be.bignumber.equal(balances[taker][orders[0].params.takerToken].minus(fillTakerTokenAmount));
expect(newBalances[taker][orders[0].params.makerToken])
.to.be.bignumber.equal(balances[taker][orders[0].params.makerToken].add(fillMakerTokenAmount));
expect(newBalances[taker][zrx.address]).to.be.bignumber
.equal(balances[taker][zrx.address].minus(takerFee));
expect(newBalances[feeRecipient][zrx.address])
.to.be.bignumber.equal(balances[feeRecipient][zrx.address].add(makerFee.add(takerFee)));
});
it('should fill all orders if cannot fill entire fillTakerTokenAmount', async () => {
const fillTakerTokenAmount = ZeroEx.toBaseUnitAmount(new BigNumber(100000), 18);
orders.forEach(order => {
balances[maker][order.params.makerToken] = balances[maker][order.params.makerToken]
.minus(order.params.makerTokenAmount);
balances[maker][order.params.takerToken] = balances[maker][order.params.takerToken]
.add(order.params.takerTokenAmount);
balances[maker][zrx.address] = balances[maker][zrx.address]
.minus(order.params.makerFee);
balances[taker][order.params.makerToken] = balances[taker][order.params.makerToken]
.add(order.params.makerTokenAmount);
balances[taker][order.params.takerToken] = balances[taker][order.params.takerToken]
.minus(order.params.takerTokenAmount);
balances[taker][zrx.address] = balances[taker][zrx.address].minus(order.params.takerFee);
balances[feeRecipient][zrx.address] =
balances[feeRecipient][zrx.address].add(order.params.makerFee.add(order.params.takerFee));
});
await exWrapper.fillOrdersUpToAsync(orders, taker, {fillTakerTokenAmount});
const newBalances = await dmyBalances.getAsync();
expect(newBalances).to.be.deep.equal(balances);
});
it('should throw when an order does not use the same takerToken', async () => {
orders = await Promise.all([
orderFactory.newSignedOrderAsync(),
orderFactory.newSignedOrderAsync({takerToken: zrx.address}),
orderFactory.newSignedOrderAsync(),
]);
return expect(
exWrapper.fillOrdersUpToAsync(
orders, taker, {fillTakerTokenAmount: ZeroEx.toBaseUnitAmount(new BigNumber(1000), 18)}),
).to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('batchCancelOrders', () => {
it('should be able to cancel multiple orders', async () => {
const cancelTakerTokenAmounts = _.map(orders, order => order.params.takerTokenAmount);
await exWrapper.batchCancelOrdersAsync(orders, maker, {cancelTakerTokenAmounts});
const res = await exWrapper.batchFillOrdersAsync(
orders, taker, {fillTakerTokenAmounts: cancelTakerTokenAmounts});
const newBalances = await dmyBalances.getAsync();
expect(balances).to.be.deep.equal(newBalances);
});
});
});
});
});

View File

@@ -23,89 +23,89 @@ const expect = chai.expect;
const web3: Web3 = (global as any).web3;
contract('MultiSigWalletWithTimeLock', (accounts: string[]) => {
const owners = [accounts[0], accounts[1]];
const SECONDS_TIME_LOCKED = 10000;
const owners = [accounts[0], accounts[1]];
const SECONDS_TIME_LOCKED = 10000;
let multiSig: ContractInstance;
let multiSigWrapper: MultiSigWrapper;
let txId: number;
let initialSecondsTimeLocked: number;
let rpc: RPC;
let multiSig: ContractInstance;
let multiSigWrapper: MultiSigWrapper;
let txId: number;
let initialSecondsTimeLocked: number;
let rpc: RPC;
before(async () => {
multiSig = await MultiSigWalletWithTimeLock.deployed();
multiSigWrapper = new MultiSigWrapper(multiSig);
before(async () => {
multiSig = await MultiSigWalletWithTimeLock.deployed();
multiSigWrapper = new MultiSigWrapper(multiSig);
const secondsTimeLocked = await multiSig.secondsTimeLocked.call();
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
rpc = new RPC();
});
describe('changeTimeLock', () => {
it('should throw when not called by wallet', async () => {
return expect(multiSig.changeTimeLock(SECONDS_TIME_LOCKED, {from: owners[0]}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
const secondsTimeLocked = await multiSig.secondsTimeLocked.call();
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
rpc = new RPC();
});
it('should throw without enough confirmations', async () => {
const destination = multiSig.address;
const from = owners[0];
const dataParams = {
name: 'changeTimeLock',
abi: MULTI_SIG_ABI,
args: [SECONDS_TIME_LOCKED],
};
const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
describe('changeTimeLock', () => {
it('should throw when not called by wallet', async () => {
return expect(multiSig.changeTimeLock(SECONDS_TIME_LOCKED, {from: owners[0]}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
txId = subRes.logs[0].args.transactionId.toNumber();
return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
it('should throw without enough confirmations', async () => {
const destination = multiSig.address;
const from = owners[0];
const dataParams = {
name: 'changeTimeLock',
abi: MULTI_SIG_ABI,
args: [SECONDS_TIME_LOCKED],
};
const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
txId = subRes.logs[0].args.transactionId.toNumber();
return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should set confirmation time with enough confirmations', async () => {
const res = await multiSig.confirmTransaction(txId, {from: owners[1]});
expect(res.logs).to.have.length(2);
const blockNum = await promisify(web3.eth.getBlockNumber)();
const blockInfo = await promisify(web3.eth.getBlock)(blockNum);
const timestamp = new BigNumber(blockInfo.timestamp);
const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.call(txId));
expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
});
it('should be executable with enough confirmations and secondsTimeLocked of 0', async () => {
expect(initialSecondsTimeLocked).to.be.equal(0);
const res = await multiSig.executeTransaction(txId);
expect(res.logs).to.have.length(2);
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call());
expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
});
const newSecondsTimeLocked = 0;
it('should throw if it has enough confirmations but is not past the time lock', async () => {
const destination = multiSig.address;
const from = owners[0];
const dataParams = {
name: 'changeTimeLock',
abi: MULTI_SIG_ABI,
args: [newSecondsTimeLocked],
};
const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
txId = subRes.logs[0].args.transactionId.toNumber();
const confRes = await multiSig.confirmTransaction(txId, {from: owners[1]});
expect(confRes.logs).to.have.length(2);
return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should execute if it has enough confirmations and is past the time lock', async () => {
await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED);
await multiSig.executeTransaction(txId);
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call());
expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
});
});
it('should set confirmation time with enough confirmations', async () => {
const res = await multiSig.confirmTransaction(txId, {from: owners[1]});
expect(res.logs).to.have.length(2);
const blockNum = await promisify(web3.eth.getBlockNumber)();
const blockInfo = await promisify(web3.eth.getBlock)(blockNum);
const timestamp = new BigNumber(blockInfo.timestamp);
const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.call(txId));
expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
});
it('should be executable with enough confirmations and secondsTimeLocked of 0', async () => {
expect(initialSecondsTimeLocked).to.be.equal(0);
const res = await multiSig.executeTransaction(txId);
expect(res.logs).to.have.length(2);
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call());
expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
});
const newSecondsTimeLocked = 0;
it('should throw if it has enough confirmations but is not past the time lock', async () => {
const destination = multiSig.address;
const from = owners[0];
const dataParams = {
name: 'changeTimeLock',
abi: MULTI_SIG_ABI,
args: [newSecondsTimeLocked],
};
const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
txId = subRes.logs[0].args.transactionId.toNumber();
const confRes = await multiSig.confirmTransaction(txId, {from: owners[1]});
expect(confRes.logs).to.have.length(2);
return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should execute if it has enough confirmations and is past the time lock', async () => {
await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED);
await multiSig.executeTransaction(txId);
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call());
expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
});
});
});

View File

@@ -15,122 +15,123 @@ chaiSetup.configure();
const expect = chai.expect;
contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: string[]) => {
const owners = [accounts[0], accounts[1]];
const requiredApprovals = 2;
const SECONDS_TIME_LOCKED = 1000000;
const owners = [accounts[0], accounts[1]];
const requiredApprovals = 2;
const SECONDS_TIME_LOCKED = 1000000;
// initialize fake addresses
const authorizedAddress = `0x${crypto.solSHA3([accounts[0]]).slice(0, 20).toString('hex')}`;
const unauthorizedAddress = `0x${crypto.solSHA3([accounts[1]]).slice(0, 20).toString('hex')}`;
// initialize fake addresses
const authorizedAddress = `0x${crypto.solSHA3([accounts[0]]).slice(0, 20).toString('hex')}`;
const unauthorizedAddress = `0x${crypto.solSHA3([accounts[1]]).slice(0, 20).toString('hex')}`;
let tokenTransferProxy: ContractInstance;
let multiSig: ContractInstance;
let multiSigWrapper: MultiSigWrapper;
let tokenTransferProxy: ContractInstance;
let multiSig: ContractInstance;
let multiSigWrapper: MultiSigWrapper;
let validDestination: string;
let validDestination: string;
beforeEach(async () => {
const initialOwner = accounts[0];
tokenTransferProxy = await TokenTransferProxy.new({from: initialOwner});
await tokenTransferProxy.addAuthorizedAddress(authorizedAddress, {from: initialOwner});
multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.new(
owners, requiredApprovals, SECONDS_TIME_LOCKED, tokenTransferProxy.address);
await tokenTransferProxy.transferOwnership(multiSig.address, {from: initialOwner});
multiSigWrapper = new MultiSigWrapper(multiSig);
validDestination = tokenTransferProxy.address;
});
describe('isFunctionRemoveAuthorizedAddress', () => {
it('should throw if data is not for removeAuthorizedAddress', async () => {
const data = multiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]);
return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data)).to.be.rejectedWith(constants.INVALID_OPCODE);
beforeEach(async () => {
const initialOwner = accounts[0];
tokenTransferProxy = await TokenTransferProxy.new({from: initialOwner});
await tokenTransferProxy.addAuthorizedAddress(authorizedAddress, {from: initialOwner});
multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.new(
owners, requiredApprovals, SECONDS_TIME_LOCKED, tokenTransferProxy.address);
await tokenTransferProxy.transferOwnership(multiSig.address, {from: initialOwner});
multiSigWrapper = new MultiSigWrapper(multiSig);
validDestination = tokenTransferProxy.address;
});
it('should return true if data is for removeAuthorizedAddress', async () => {
const data = multiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]);
const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.call(data);
expect(isFunctionRemoveAuthorizedAddress).to.be.true();
});
});
describe('isFunctionRemoveAuthorizedAddress', () => {
it('should throw if data is not for removeAuthorizedAddress', async () => {
const data = multiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]);
return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
describe('executeRemoveAuthorizedAddress', () => {
it('should throw without the required confirmations', async () => {
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',
abi: PROXY_ABI,
args: [authorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
it('should return true if data is for removeAuthorizedAddress', async () => {
const data = multiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]);
const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.call(data);
expect(isFunctionRemoveAuthorizedAddress).to.be.true();
});
});
it('should throw if tx destination is not the tokenTransferProxy', async () => {
const invalidTokenTransferProxy = await TokenTransferProxy.new();
const invalidDestination = invalidTokenTransferProxy.address;
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',
abi: PROXY_ABI,
args: [authorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
await multiSig.confirmTransaction(txId, {from: owners[1]});
const isConfirmed = await multiSig.isConfirmed.call(txId);
expect(isConfirmed).to.be.true();
describe('executeRemoveAuthorizedAddress', () => {
it('should throw without the required confirmations', async () => {
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',
abi: PROXY_ABI,
args: [authorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if tx destination is not the tokenTransferProxy', async () => {
const invalidTokenTransferProxy = await TokenTransferProxy.new();
const invalidDestination = invalidTokenTransferProxy.address;
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',
abi: PROXY_ABI,
args: [authorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
await multiSig.confirmTransaction(txId, {from: owners[1]});
const isConfirmed = await multiSig.isConfirmed.call(txId);
expect(isConfirmed).to.be.true();
return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if tx data is not for removeAuthorizedAddress', async () => {
const dataParams: TransactionDataParams = {
name: 'addAuthorizedAddress',
abi: PROXY_ABI,
args: [unauthorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
await multiSig.confirmTransaction(txId, {from: owners[1]});
const isConfirmed = await multiSig.isConfirmed.call(txId);
expect(isConfirmed).to.be.true();
return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => {
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',
abi: PROXY_ABI,
args: [authorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
await multiSig.confirmTransaction(txId, {from: owners[1]});
const isConfirmed = await multiSig.isConfirmed.call(txId);
expect(isConfirmed).to.be.true();
await multiSig.executeRemoveAuthorizedAddress(txId);
const isAuthorized = await tokenTransferProxy.authorized.call(authorizedAddress);
expect(isAuthorized).to.be.false();
});
it('should throw if already executed', async () => {
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',
abi: PROXY_ABI,
args: [authorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
await multiSig.confirmTransaction(txId, {from: owners[1]});
const isConfirmed = await multiSig.isConfirmed.call(txId);
expect(isConfirmed).to.be.true();
await multiSig.executeRemoveAuthorizedAddress(txId);
const tx = await multiSig.transactions.call(txId);
const isExecuted = tx[3];
expect(isExecuted).to.be.true();
return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
it('should throw if tx data is not for removeAuthorizedAddress', async () => {
const dataParams: TransactionDataParams = {
name: 'addAuthorizedAddress',
abi: PROXY_ABI,
args: [unauthorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
await multiSig.confirmTransaction(txId, {from: owners[1]});
const isConfirmed = await multiSig.isConfirmed.call(txId);
expect(isConfirmed).to.be.true();
return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => {
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',
abi: PROXY_ABI,
args: [authorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
await multiSig.confirmTransaction(txId, {from: owners[1]});
const isConfirmed = await multiSig.isConfirmed.call(txId);
expect(isConfirmed).to.be.true();
await multiSig.executeRemoveAuthorizedAddress(txId);
const isAuthorized = await tokenTransferProxy.authorized.call(authorizedAddress);
expect(isAuthorized).to.be.false();
});
it('should throw if already executed', async () => {
const dataParams: TransactionDataParams = {
name: 'removeAuthorizedAddress',
abi: PROXY_ABI,
args: [authorizedAddress],
};
const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
const txId = res.logs[0].args.transactionId.toString();
await multiSig.confirmTransaction(txId, {from: owners[1]});
const isConfirmed = await multiSig.isConfirmed.call(txId);
expect(isConfirmed).to.be.true();
await multiSig.executeRemoveAuthorizedAddress(txId);
const tx = await multiSig.transactions.call(txId);
const isExecuted = tx[3];
expect(isExecuted).to.be.true();
return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
});

View File

@@ -15,198 +15,198 @@ chaiSetup.configure();
const expect = chai.expect;
contract('TokenRegistry', (accounts: string[]) => {
const owner = accounts[0];
const notOwner = accounts[1];
const owner = accounts[0];
const notOwner = accounts[1];
const tokenAddress1 = `0x${ethUtil.setLength(ethUtil.toBuffer('0x1'), 20, false).toString('hex')}`;
const tokenAddress2 = `0x${ethUtil.setLength(ethUtil.toBuffer('0x2'), 20, false).toString('hex')}`;
const tokenAddress1 = `0x${ethUtil.setLength(ethUtil.toBuffer('0x1'), 20, false).toString('hex')}`;
const tokenAddress2 = `0x${ethUtil.setLength(ethUtil.toBuffer('0x2'), 20, false).toString('hex')}`;
const token1 = {
address: tokenAddress1,
name: 'testToken1',
symbol: 'TT1',
decimals: 18,
ipfsHash: `0x${ethUtil.sha3('ipfs1').toString('hex')}`,
swarmHash: `0x${ethUtil.sha3('swarm1').toString('hex')}`,
};
const token1 = {
address: tokenAddress1,
name: 'testToken1',
symbol: 'TT1',
decimals: 18,
ipfsHash: `0x${ethUtil.sha3('ipfs1').toString('hex')}`,
swarmHash: `0x${ethUtil.sha3('swarm1').toString('hex')}`,
};
const token2 = {
address: tokenAddress2,
name: 'testToken2',
symbol: 'TT2',
decimals: 18,
ipfsHash: `0x${ethUtil.sha3('ipfs2').toString('hex')}`,
swarmHash: `0x${ethUtil.sha3('swarm2').toString('hex')}`,
};
const token2 = {
address: tokenAddress2,
name: 'testToken2',
symbol: 'TT2',
decimals: 18,
ipfsHash: `0x${ethUtil.sha3('ipfs2').toString('hex')}`,
swarmHash: `0x${ethUtil.sha3('swarm2').toString('hex')}`,
};
const nullToken = {
address: ZeroEx.NULL_ADDRESS,
name: '',
symbol: '',
decimals: 0,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
};
const nullToken = {
address: ZeroEx.NULL_ADDRESS,
name: '',
symbol: '',
decimals: 0,
ipfsHash: constants.NULL_BYTES,
swarmHash: constants.NULL_BYTES,
};
let tokenReg: ContractInstance;
let tokenRegWrapper: TokenRegWrapper;
let tokenReg: ContractInstance;
let tokenRegWrapper: TokenRegWrapper;
beforeEach(async () => {
tokenReg = await TokenRegistry.new();
tokenRegWrapper = new TokenRegWrapper(tokenReg);
});
describe('addToken', () => {
it('should throw when not called by owner', async () => {
return expect(tokenRegWrapper.addTokenAsync(token1, notOwner)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should add token metadata when called by owner', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address);
expect(tokenData).to.be.deep.equal(token1);
});
it('should throw if token already exists', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
return expect(tokenRegWrapper.addTokenAsync(token1, owner)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if token address is null', async () => {
return expect(tokenRegWrapper.addTokenAsync(nullToken, owner)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if name already exists', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
const duplicateNameToken = _.assign({}, token2, {name: token1.name});
return expect(tokenRegWrapper.addTokenAsync(duplicateNameToken, owner))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if symbol already exists', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
const duplicateSymbolToken = _.assign({}, token2, {symbol: token1.symbol});
return expect(tokenRegWrapper.addTokenAsync(duplicateSymbolToken, owner))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('after addToken', () => {
beforeEach(async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
tokenReg = await TokenRegistry.new();
tokenRegWrapper = new TokenRegWrapper(tokenReg);
});
describe('getTokenByName', () => {
it('should return token metadata when given the token name', async () => {
const tokenData = await tokenRegWrapper.getTokenByNameAsync(token1.name);
expect(tokenData).to.be.deep.equal(token1);
});
describe('addToken', () => {
it('should throw when not called by owner', async () => {
return expect(tokenRegWrapper.addTokenAsync(token1, notOwner)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should add token metadata when called by owner', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address);
expect(tokenData).to.be.deep.equal(token1);
});
it('should throw if token already exists', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
return expect(tokenRegWrapper.addTokenAsync(token1, owner)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if token address is null', async () => {
return expect(tokenRegWrapper.addTokenAsync(nullToken, owner)).to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if name already exists', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
const duplicateNameToken = _.assign({}, token2, {name: token1.name});
return expect(tokenRegWrapper.addTokenAsync(duplicateNameToken, owner))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if symbol already exists', async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
const duplicateSymbolToken = _.assign({}, token2, {symbol: token1.symbol});
return expect(tokenRegWrapper.addTokenAsync(duplicateSymbolToken, owner))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('getTokenBySymbol', () => {
it('should return token metadata when given the token symbol', async () => {
const tokenData = await tokenRegWrapper.getTokenBySymbolAsync(token1.symbol);
expect(tokenData).to.be.deep.equal(token1);
});
describe('after addToken', () => {
beforeEach(async () => {
await tokenRegWrapper.addTokenAsync(token1, owner);
});
describe('getTokenByName', () => {
it('should return token metadata when given the token name', async () => {
const tokenData = await tokenRegWrapper.getTokenByNameAsync(token1.name);
expect(tokenData).to.be.deep.equal(token1);
});
});
describe('getTokenBySymbol', () => {
it('should return token metadata when given the token symbol', async () => {
const tokenData = await tokenRegWrapper.getTokenBySymbolAsync(token1.symbol);
expect(tokenData).to.be.deep.equal(token1);
});
});
describe('setTokenName', () => {
it('should throw when not called by owner', async () => {
return expect(tokenReg.setTokenName(token1.address, token2.name, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should change the token name when called by owner', async () => {
const res = await tokenReg.setTokenName(token1.address, token2.name, {from: owner});
expect(res.logs).to.have.length(1);
const [newData, oldData] = await Promise.all([
tokenRegWrapper.getTokenByNameAsync(token2.name),
tokenRegWrapper.getTokenByNameAsync(token1.name),
]);
const expectedNewData = _.assign({}, token1, {name: token2.name});
const expectedOldData = nullToken;
expect(newData).to.be.deep.equal(expectedNewData);
expect(oldData).to.be.deep.equal(expectedOldData);
});
it('should throw if the name already exists', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner);
return expect(tokenReg.setTokenName(token1.address, token2.name, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if token does not exist', async () => {
return expect(tokenReg.setTokenName(nullToken.address, token2.name, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('setTokenSymbol', () => {
it('should throw when not called by owner', async () => {
return expect(tokenReg.setTokenSymbol(token1.address, token2.symbol, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should change the token symbol when called by owner', async () => {
const res = await tokenReg.setTokenSymbol(token1.address, token2.symbol, {from: owner});
expect(res.logs).to.have.length(1);
const [newData, oldData] = await Promise.all([
tokenRegWrapper.getTokenBySymbolAsync(token2.symbol),
tokenRegWrapper.getTokenBySymbolAsync(token1.symbol),
]);
const expectedNewData = _.assign({}, token1, {symbol: token2.symbol});
const expectedOldData = nullToken;
expect(newData).to.be.deep.equal(expectedNewData);
expect(oldData).to.be.deep.equal(expectedOldData);
});
it('should throw if the symbol already exists', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner);
return expect(tokenReg.setTokenSymbol(token1.address, token2.symbol, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if token does not exist', async () => {
return expect(tokenReg.setTokenSymbol(nullToken.address, token2.symbol, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('removeToken', () => {
it('should throw if not called by owner', async () => {
const index = 0;
return expect(tokenReg.removeToken(token1.address, index, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should remove token metadata when called by owner', async () => {
const index = 0;
const res = await tokenReg.removeToken(token1.address, index, {from: owner});
expect(res.logs).to.have.length(1);
const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address);
expect(tokenData).to.be.deep.equal(nullToken);
});
it('should throw if token does not exist', async () => {
const index = 0;
return expect(tokenReg.removeToken(nullToken.address, index, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if token at given index does not match address', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner);
const incorrectIndex = 0;
return expect(tokenReg.removeToken(token2.address, incorrectIndex, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
});
describe('setTokenName', () => {
it('should throw when not called by owner', async () => {
return expect(tokenReg.setTokenName(token1.address, token2.name, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should change the token name when called by owner', async () => {
const res = await tokenReg.setTokenName(token1.address, token2.name, {from: owner});
expect(res.logs).to.have.length(1);
const [newData, oldData] = await Promise.all([
tokenRegWrapper.getTokenByNameAsync(token2.name),
tokenRegWrapper.getTokenByNameAsync(token1.name),
]);
const expectedNewData = _.assign({}, token1, {name: token2.name});
const expectedOldData = nullToken;
expect(newData).to.be.deep.equal(expectedNewData);
expect(oldData).to.be.deep.equal(expectedOldData);
});
it('should throw if the name already exists', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner);
return expect(tokenReg.setTokenName(token1.address, token2.name, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if token does not exist', async () => {
return expect(tokenReg.setTokenName(nullToken.address, token2.name, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('setTokenSymbol', () => {
it('should throw when not called by owner', async () => {
return expect(tokenReg.setTokenSymbol(token1.address, token2.symbol, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should change the token symbol when called by owner', async () => {
const res = await tokenReg.setTokenSymbol(token1.address, token2.symbol, {from: owner});
expect(res.logs).to.have.length(1);
const [newData, oldData] = await Promise.all([
tokenRegWrapper.getTokenBySymbolAsync(token2.symbol),
tokenRegWrapper.getTokenBySymbolAsync(token1.symbol),
]);
const expectedNewData = _.assign({}, token1, {symbol: token2.symbol});
const expectedOldData = nullToken;
expect(newData).to.be.deep.equal(expectedNewData);
expect(oldData).to.be.deep.equal(expectedOldData);
});
it('should throw if the symbol already exists', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner);
return expect(tokenReg.setTokenSymbol(token1.address, token2.symbol, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if token does not exist', async () => {
return expect(tokenReg.setTokenSymbol(nullToken.address, token2.symbol, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('removeToken', () => {
it('should throw if not called by owner', async () => {
const index = 0;
return expect(tokenReg.removeToken(token1.address, index, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should remove token metadata when called by owner', async () => {
const index = 0;
const res = await tokenReg.removeToken(token1.address, index, {from: owner});
expect(res.logs).to.have.length(1);
const tokenData = await tokenRegWrapper.getTokenMetaDataAsync(token1.address);
expect(tokenData).to.be.deep.equal(nullToken);
});
it('should throw if token does not exist', async () => {
const index = 0;
return expect(tokenReg.removeToken(nullToken.address, index, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should throw if token at given index does not match address', async () => {
await tokenRegWrapper.addTokenAsync(token2, owner);
const incorrectIndex = 0;
return expect(tokenReg.removeToken(token2.address, incorrectIndex, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
});
});

View File

@@ -9,75 +9,75 @@ const expect = chai.expect;
const TokenTransferProxy = artifacts.require('./db/TokenTransferProxy.sol');
contract('TokenTransferProxy', (accounts: string[]) => {
const owner = accounts[0];
const notOwner = accounts[1];
const owner = accounts[0];
const notOwner = accounts[1];
let tokenTransferProxy: ContractInstance;
let authorized: string;
let notAuthorized = owner;
let tokenTransferProxy: ContractInstance;
let authorized: string;
let notAuthorized = owner;
before(async () => {
tokenTransferProxy = await TokenTransferProxy.deployed();
});
describe('addAuthorizedAddress', () => {
it('should throw if not called by owner', async () => {
return expect(tokenTransferProxy.addAuthorizedAddress(notOwner, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
before(async () => {
tokenTransferProxy = await TokenTransferProxy.deployed();
});
it('should allow owner to add an authorized address', async () => {
await tokenTransferProxy.addAuthorizedAddress(notAuthorized, {from: owner});
authorized = notAuthorized;
notAuthorized = null;
const isAuthorized = await tokenTransferProxy.authorized.call(authorized);
expect(isAuthorized).to.be.true();
describe('addAuthorizedAddress', () => {
it('should throw if not called by owner', async () => {
return expect(tokenTransferProxy.addAuthorizedAddress(notOwner, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
it('should allow owner to add an authorized address', async () => {
await tokenTransferProxy.addAuthorizedAddress(notAuthorized, {from: owner});
authorized = notAuthorized;
notAuthorized = null;
const isAuthorized = await tokenTransferProxy.authorized.call(authorized);
expect(isAuthorized).to.be.true();
});
it('should throw if owner attempts to authorize a duplicate address', async () => {
return expect(tokenTransferProxy.addAuthorizedAddress(authorized, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
it('should throw if owner attempts to authorize a duplicate address', async () => {
return expect(tokenTransferProxy.addAuthorizedAddress(authorized, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('removeAuthorizedAddress', () => {
it('should throw if not called by owner', async () => {
return expect(tokenTransferProxy.removeAuthorizedAddress(authorized, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
describe('removeAuthorizedAddress', () => {
it('should throw if not called by owner', async () => {
return expect(tokenTransferProxy.removeAuthorizedAddress(authorized, {from: notOwner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
it('should allow owner to remove an authorized address', async () => {
await tokenTransferProxy.removeAuthorizedAddress(authorized, {from: owner});
notAuthorized = authorized;
authorized = null;
const isAuthorized = await tokenTransferProxy.authorized.call(notAuthorized);
expect(isAuthorized).to.be.false();
});
it('should throw if owner attempts to remove an address that is not authorized', async () => {
return expect(tokenTransferProxy.removeAuthorizedAddress(notAuthorized, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
it('should allow owner to remove an authorized address', async () => {
await tokenTransferProxy.removeAuthorizedAddress(authorized, {from: owner});
notAuthorized = authorized;
authorized = null;
describe('getAuthorizedAddresses', () => {
it('should return all authorized addresses', async () => {
const initial = await tokenTransferProxy.getAuthorizedAddresses();
expect(initial).to.have.length(1);
await tokenTransferProxy.addAuthorizedAddress(notAuthorized, {from: owner});
const isAuthorized = await tokenTransferProxy.authorized.call(notAuthorized);
expect(isAuthorized).to.be.false();
authorized = notAuthorized;
notAuthorized = null;
const afterAdd = await tokenTransferProxy.getAuthorizedAddresses();
expect(afterAdd).to.have.length(2);
expect(afterAdd).to.include(authorized);
await tokenTransferProxy.removeAuthorizedAddress(authorized, {from: owner});
notAuthorized = authorized;
authorized = null;
const afterRemove = await tokenTransferProxy.getAuthorizedAddresses();
expect(afterRemove).to.have.length(1);
});
});
it('should throw if owner attempts to remove an address that is not authorized', async () => {
return expect(tokenTransferProxy.removeAuthorizedAddress(notAuthorized, {from: owner}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
});
describe('getAuthorizedAddresses', () => {
it('should return all authorized addresses', async () => {
const initial = await tokenTransferProxy.getAuthorizedAddresses();
expect(initial).to.have.length(1);
await tokenTransferProxy.addAuthorizedAddress(notAuthorized, {from: owner});
authorized = notAuthorized;
notAuthorized = null;
const afterAdd = await tokenTransferProxy.getAuthorizedAddresses();
expect(afterAdd).to.have.length(2);
expect(afterAdd).to.include(authorized);
await tokenTransferProxy.removeAuthorizedAddress(authorized, {from: owner});
notAuthorized = authorized;
authorized = null;
const afterRemove = await tokenTransferProxy.getAuthorizedAddresses();
expect(afterRemove).to.have.length(1);
});
});
});

View File

@@ -9,58 +9,59 @@ import {chaiSetup} from '../utils/chai_setup';
chaiSetup.configure();
const expect = chai.expect;
const {
TokenTransferProxy,
DummyToken,
TokenRegistry,
TokenTransferProxy,
DummyToken,
TokenRegistry,
} = new Artifacts(artifacts);
contract('TokenTransferProxy', (accounts: string[]) => {
const INIT_BAL = 100000000;
const INIT_ALLOW = 100000000;
const INIT_BAL = 100000000;
const INIT_ALLOW = 100000000;
const owner = accounts[0];
const notAuthorized = owner;
const owner = accounts[0];
const notAuthorized = owner;
let tokenTransferProxy: ContractInstance;
let tokenRegistry: ContractInstance;
let rep: ContractInstance;
let dmyBalances: Balances;
let tokenTransferProxy: ContractInstance;
let tokenRegistry: ContractInstance;
let rep: ContractInstance;
let dmyBalances: Balances;
before(async () => {
[tokenTransferProxy, tokenRegistry] = await Promise.all([
TokenTransferProxy.deployed(),
TokenRegistry.deployed(),
]);
const repAddress = await tokenRegistry.getTokenAddressBySymbol('REP');
rep = DummyToken.at(repAddress);
before(async () => {
[tokenTransferProxy, tokenRegistry] = await Promise.all([
TokenTransferProxy.deployed(),
TokenRegistry.deployed(),
]);
const repAddress = await tokenRegistry.getTokenAddressBySymbol('REP');
rep = DummyToken.at(repAddress);
dmyBalances = new Balances([rep], [accounts[0], accounts[1]]);
await Promise.all([
rep.approve(TokenTransferProxy.address, INIT_ALLOW, {from: accounts[0]}),
rep.setBalance(accounts[0], INIT_BAL, {from: owner}),
rep.approve(TokenTransferProxy.address, INIT_ALLOW, {from: accounts[1]}),
rep.setBalance(accounts[1], INIT_BAL, {from: owner}),
]);
});
describe('transferFrom', () => {
it('should throw when called by an unauthorized address', async () => {
expect(tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1], 1000, {from: notAuthorized}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
dmyBalances = new Balances([rep], [accounts[0], accounts[1]]);
await Promise.all([
rep.approve(TokenTransferProxy.address, INIT_ALLOW, {from: accounts[0]}),
rep.setBalance(accounts[0], INIT_BAL, {from: owner}),
rep.approve(TokenTransferProxy.address, INIT_ALLOW, {from: accounts[1]}),
rep.setBalance(accounts[1], INIT_BAL, {from: owner}),
]);
});
it('should allow an authorized address to transfer', async () => {
const balances = await dmyBalances.getAsync();
describe('transferFrom', () => {
it('should throw when called by an unauthorized address', async () => {
expect(tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1], 1000, {from: notAuthorized}))
.to.be.rejectedWith(constants.INVALID_OPCODE);
});
await tokenTransferProxy.addAuthorizedAddress(notAuthorized, {from: owner});
const transferAmt = 10000;
await tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1], transferAmt, {from: notAuthorized});
it('should allow an authorized address to transfer', async () => {
const balances = await dmyBalances.getAsync();
const newBalances = await dmyBalances.getAsync();
expect(newBalances[accounts[0]][rep.address])
.to.be.bignumber.equal(balances[accounts[0]][rep.address].minus(transferAmt));
expect(newBalances[accounts[1]][rep.address])
.to.be.bignumber.equal(balances[accounts[1]][rep.address].add(transferAmt));
await tokenTransferProxy.addAuthorizedAddress(notAuthorized, {from: owner});
const transferAmt = 10000;
await tokenTransferProxy.transferFrom(rep.address, accounts[0], accounts[1],
transferAmt, {from: notAuthorized});
const newBalances = await dmyBalances.getAsync();
expect(newBalances[accounts[0]][rep.address])
.to.be.bignumber.equal(balances[accounts[0]][rep.address].minus(transferAmt));
expect(newBalances[accounts[1]][rep.address])
.to.be.bignumber.equal(balances[accounts[1]][rep.address].add(transferAmt));
});
});
});
});

View File

@@ -14,102 +14,102 @@ chaiSetup.configure();
const expect = chai.expect;
contract('UnlimitedAllowanceToken', (accounts: string[]) => {
const zeroEx = new ZeroEx(web3.currentProvider);
const owner = accounts[0];
const spender = accounts[1];
const zeroEx = new ZeroEx(web3.currentProvider);
const owner = accounts[0];
const spender = accounts[1];
const MAX_MINT_VALUE = new BigNumber(100000000000000000000);
let tokenAddress: string;
let token: ContractInstance;
const MAX_MINT_VALUE = new BigNumber(100000000000000000000);
let tokenAddress: string;
let token: ContractInstance;
beforeEach(async () => {
token = await DummyToken.new({from: owner});
await token.mint(MAX_MINT_VALUE, {from: owner});
tokenAddress = token.address;
});
describe('transfer', () => {
it('should transfer balance from sender to receiver', async () => {
const receiver = spender;
const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = new BigNumber(1);
await zeroEx.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer);
const finalOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const finalReceiverBalance = await zeroEx.token.getBalanceAsync(tokenAddress, receiver);
const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer);
const expectedFinalReceiverBalance = amountToTransfer;
expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance);
expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance);
beforeEach(async () => {
token = await DummyToken.new({from: owner});
await token.mint(MAX_MINT_VALUE, {from: owner});
tokenAddress = token.address;
});
it('should return true on a 0 value transfer', async () => {
const didReturnTrue = await token.transfer.call(spender, 0, {from: owner});
expect(didReturnTrue).to.be.true();
});
});
describe('transfer', () => {
it('should transfer balance from sender to receiver', async () => {
const receiver = spender;
const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = new BigNumber(1);
await zeroEx.token.transferAsync(tokenAddress, owner, receiver, amountToTransfer);
const finalOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const finalReceiverBalance = await zeroEx.token.getBalanceAsync(tokenAddress, receiver);
describe('transferFrom', () => {
it('should return false if owner has insufficient balance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = ownerBalance.plus(1);
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer);
const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.false();
const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer);
const expectedFinalReceiverBalance = amountToTransfer;
expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance);
expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance);
});
it('should return true on a 0 value transfer', async () => {
const didReturnTrue = await token.transfer.call(spender, 0, {from: owner});
expect(didReturnTrue).to.be.true();
});
});
it('should return false if spender has insufficient allowance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = ownerBalance;
describe('transferFrom', () => {
it('should return false if owner has insufficient balance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = ownerBalance.plus(1);
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, amountToTransfer);
const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.false();
});
const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender);
const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0;
expect(spenderAllowanceIsInsufficient).to.be.true();
it('should return false if spender has insufficient allowance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = ownerBalance;
const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.false();
const spenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender);
const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0;
expect(spenderAllowanceIsInsufficient).to.be.true();
const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.false();
});
it('should return true on a 0 value transfer', async () => {
const amountToTransfer = 0;
const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.true();
});
it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance);
await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer);
const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender);
expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance);
});
it('should transfer the correct balances if spender has sufficient allowance', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance);
await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer);
const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender);
expect(newOwnerBalance).to.be.bignumber.equal(0);
expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance);
});
it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance);
await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer);
const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender);
expect(newSpenderAllowance).to.be.bignumber.equal(0);
});
});
it('should return true on a 0 value transfer', async () => {
const amountToTransfer = 0;
const didReturnTrue = await token.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.true();
});
it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance);
await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer);
const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender);
expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance);
});
it('should transfer the correct balances if spender has sufficient allowance', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance);
await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer);
const newOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const newSpenderBalance = await zeroEx.token.getBalanceAsync(tokenAddress, spender);
expect(newOwnerBalance).to.be.bignumber.equal(0);
expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance);
});
it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(tokenAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
await zeroEx.token.setAllowanceAsync(tokenAddress, owner, spender, initSpenderAllowance);
await zeroEx.token.transferFromAsync(tokenAddress, owner, spender, spender, amountToTransfer);
const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(tokenAddress, owner, spender);
expect(newSpenderAllowance).to.be.bignumber.equal(0);
});
});
});

View File

@@ -14,155 +14,155 @@ const {Exchange, ZRXToken} = new Artifacts(artifacts);
const web3: Web3 = (global as any).web3;
contract('ZRXToken', (accounts: string[]) => {
const owner = accounts[0];
const spender = accounts[1];
let zeroEx: ZeroEx;
const owner = accounts[0];
const spender = accounts[1];
let zeroEx: ZeroEx;
let MAX_UINT: BigNumber;
let MAX_UINT: BigNumber;
let zrx: ContractInstance;
let zrxAddress: string;
let zrx: ContractInstance;
let zrxAddress: string;
beforeEach(async () => {
zeroEx = new ZeroEx(web3.currentProvider, {
exchangeContractAddress: Exchange.address,
});
zrxAddress = await zeroEx.exchange.getZRXTokenAddressAsync();
zrx = await ZRXToken.at(zrxAddress);
MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
});
describe('constants', () => {
it('should have 18 decimals', async () => {
const decimals = new BigNumber(await zrx.decimals.call());
const expectedDecimals = 18;
expect(decimals).to.be.bignumber.equal(expectedDecimals);
beforeEach(async () => {
zeroEx = new ZeroEx(web3.currentProvider, {
exchangeContractAddress: Exchange.address,
});
zrxAddress = await zeroEx.exchange.getZRXTokenAddressAsync();
zrx = await ZRXToken.at(zrxAddress);
MAX_UINT = zeroEx.token.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
});
it('should have a total supply of 1 billion tokens', async () => {
const totalSupply = new BigNumber(await zrx.totalSupply.call());
const expectedTotalSupply = 1000000000;
expect(ZeroEx.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply);
describe('constants', () => {
it('should have 18 decimals', async () => {
const decimals = new BigNumber(await zrx.decimals.call());
const expectedDecimals = 18;
expect(decimals).to.be.bignumber.equal(expectedDecimals);
});
it('should have a total supply of 1 billion tokens', async () => {
const totalSupply = new BigNumber(await zrx.totalSupply.call());
const expectedTotalSupply = 1000000000;
expect(ZeroEx.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply);
});
it('should be named 0x Protocol Token', async () => {
const name = await zrx.name.call();
const expectedName = '0x Protocol Token';
expect(name).to.be.equal(expectedName);
});
it('should have the symbol ZRX', async () => {
const symbol = await zrx.symbol.call();
const expectedSymbol = 'ZRX';
expect(symbol).to.be.equal(expectedSymbol);
});
});
it('should be named 0x Protocol Token', async () => {
const name = await zrx.name.call();
const expectedName = '0x Protocol Token';
expect(name).to.be.equal(expectedName);
describe('constructor', () => {
it('should initialize owner balance to totalSupply', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const totalSupply = new BigNumber(await zrx.totalSupply.call());
expect(totalSupply).to.be.bignumber.equal(ownerBalance);
});
});
it('should have the symbol ZRX', async () => {
const symbol = await zrx.symbol.call();
const expectedSymbol = 'ZRX';
expect(symbol).to.be.equal(expectedSymbol);
});
});
describe('transfer', () => {
it('should transfer balance from sender to receiver', async () => {
const receiver = spender;
const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = new BigNumber(1);
const txHash = await zeroEx.token.transferAsync(zrxAddress, owner, receiver, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const finalOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const finalReceiverBalance = await zeroEx.token.getBalanceAsync(zrxAddress, receiver);
describe('constructor', () => {
it('should initialize owner balance to totalSupply', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const totalSupply = new BigNumber(await zrx.totalSupply.call());
expect(totalSupply).to.be.bignumber.equal(ownerBalance);
});
});
const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer);
const expectedFinalReceiverBalance = amountToTransfer;
expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance);
expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance);
});
describe('transfer', () => {
it('should transfer balance from sender to receiver', async () => {
const receiver = spender;
const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = new BigNumber(1);
const txHash = await zeroEx.token.transferAsync(zrxAddress, owner, receiver, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const finalOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const finalReceiverBalance = await zeroEx.token.getBalanceAsync(zrxAddress, receiver);
const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer);
const expectedFinalReceiverBalance = amountToTransfer;
expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance);
expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance);
it('should return true on a 0 value transfer', async () => {
const didReturnTrue = await zrx.transfer.call(spender, 0, {from: owner});
expect(didReturnTrue).to.be.true();
});
});
it('should return true on a 0 value transfer', async () => {
const didReturnTrue = await zrx.transfer.call(spender, 0, {from: owner});
expect(didReturnTrue).to.be.true();
describe('transferFrom', () => {
it('should return false if owner has insufficient balance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = ownerBalance.plus(1);
let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.false();
// Reset allowance
txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, new BigNumber(0));
await zeroEx.awaitTransactionMinedAsync(txHash);
});
it('should return false if spender has insufficient allowance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = ownerBalance;
const spenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender);
const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0;
expect(spenderAllowanceIsInsufficient).to.be.true();
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.false();
});
it('should return true on a 0 value transfer', async () => {
const amountToTransfer = 0;
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.true();
});
it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = MAX_UINT;
let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance);
await zeroEx.awaitTransactionMinedAsync(txHash);
txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender);
expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance);
// Restore balance
txHash = await zeroEx.token.transferAsync(zrxAddress, spender, owner, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
});
it('should transfer the correct balances if spender has sufficient allowance', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const initSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance);
await zeroEx.awaitTransactionMinedAsync(txHash);
txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const newOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const newSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender);
expect(newOwnerBalance).to.be.bignumber.equal(0);
expect(newSpenderBalance).to.be.bignumber.equal(initSpenderBalance.plus(initOwnerBalance));
});
it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance);
await zeroEx.awaitTransactionMinedAsync(txHash);
txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender);
expect(newSpenderAllowance).to.be.bignumber.equal(0);
});
});
});
describe('transferFrom', () => {
it('should return false if owner has insufficient balance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = ownerBalance.plus(1);
let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.false();
// Reset allowance
txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, new BigNumber(0));
await zeroEx.awaitTransactionMinedAsync(txHash);
});
it('should return false if spender has insufficient allowance', async () => {
const ownerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = ownerBalance;
const spenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender);
const spenderAllowanceIsInsufficient = spenderAllowance.cmp(amountToTransfer) < 0;
expect(spenderAllowanceIsInsufficient).to.be.true();
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.false();
});
it('should return true on a 0 value transfer', async () => {
const amountToTransfer = 0;
const didReturnTrue = await zrx.transferFrom.call(owner, spender, amountToTransfer, {from: spender});
expect(didReturnTrue).to.be.true();
});
it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = MAX_UINT;
let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance);
await zeroEx.awaitTransactionMinedAsync(txHash);
txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender);
expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance);
// Restore balance
txHash = await zeroEx.token.transferAsync(zrxAddress, spender, owner, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
});
it('should transfer the correct balances if spender has sufficient allowance', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const initSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance);
await zeroEx.awaitTransactionMinedAsync(txHash);
txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const newOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const newSpenderBalance = await zeroEx.token.getBalanceAsync(zrxAddress, spender);
expect(newOwnerBalance).to.be.bignumber.equal(0);
expect(newSpenderBalance).to.be.bignumber.equal(initSpenderBalance.plus(initOwnerBalance));
});
it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => {
const initOwnerBalance = await zeroEx.token.getBalanceAsync(zrxAddress, owner);
const amountToTransfer = initOwnerBalance;
const initSpenderAllowance = initOwnerBalance;
let txHash = await zeroEx.token.setAllowanceAsync(zrxAddress, owner, spender, initSpenderAllowance);
await zeroEx.awaitTransactionMinedAsync(txHash);
txHash = await zeroEx.token.transferFromAsync(zrxAddress, owner, spender, spender, amountToTransfer);
await zeroEx.awaitTransactionMinedAsync(txHash);
const newSpenderAllowance = await zeroEx.token.getAllowanceAsync(zrxAddress, owner, spender);
expect(newSpenderAllowance).to.be.bignumber.equal(0);
});
});
});

View File

@@ -1,17 +1,17 @@
module.exports = {
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*", // Match any network id
networks: {
development: {
host: "localhost",
port: 8545,
network_id: "*", // Match any network id
},
kovan: {
host: "localhost",
port: 8546,
network_id: "42",
gas: 4612388,
},
},
kovan: {
host: "localhost",
port: 8546,
network_id: "42",
gas: 4612388,
},
},
test_directory: "transpiled/test",
migrations_directory: "transpiled/migrations",
test_directory: "transpiled/test",
migrations_directory: "transpiled/migrations",
};

View File

@@ -1,25 +1,25 @@
export class Artifacts {
public Migrations: any;
public TokenTransferProxy: any;
public TokenRegistry: any;
public MultiSigWalletWithTimeLock: any;
public Exchange: any;
public ZRXToken: any;
public DummyToken: any;
public EtherToken: any;
public MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: any;
public MaliciousToken: any;
constructor(artifacts: any) {
this.Migrations = artifacts.require('Migrations');
this.TokenTransferProxy = artifacts.require('TokenTransferProxy');
this.TokenRegistry = artifacts.require('TokenRegistry');
this.MultiSigWalletWithTimeLock = artifacts.require('MultiSigWalletWithTimeLock');
this.Exchange = artifacts.require('Exchange');
this.ZRXToken = artifacts.require('ZRXToken');
this.DummyToken = artifacts.require('DummyToken');
this.EtherToken = artifacts.require('EtherToken');
this.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = artifacts.require(
'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress');
this.MaliciousToken = artifacts.require('MaliciousToken');
}
public Migrations: any;
public TokenTransferProxy: any;
public TokenRegistry: any;
public MultiSigWalletWithTimeLock: any;
public Exchange: any;
public ZRXToken: any;
public DummyToken: any;
public EtherToken: any;
public MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress: any;
public MaliciousToken: any;
constructor(artifacts: any) {
this.Migrations = artifacts.require('Migrations');
this.TokenTransferProxy = artifacts.require('TokenTransferProxy');
this.TokenRegistry = artifacts.require('TokenRegistry');
this.MultiSigWalletWithTimeLock = artifacts.require('MultiSigWalletWithTimeLock');
this.Exchange = artifacts.require('Exchange');
this.ZRXToken = artifacts.require('ZRXToken');
this.DummyToken = artifacts.require('DummyToken');
this.EtherToken = artifacts.require('EtherToken');
this.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress = artifacts.require(
'MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress');
this.MaliciousToken = artifacts.require('MaliciousToken');
}
}

View File

@@ -7,24 +7,24 @@ import {BalancesByOwner, ContractInstance} from './types';
bigNumberConfigs.configure();
export class Balances {
private tokenContractInstances: ContractInstance[];
private ownerAddresses: string[];
constructor(tokenContractInstances: ContractInstance[], ownerAddresses: string[]) {
this.tokenContractInstances = tokenContractInstances;
this.ownerAddresses = ownerAddresses;
}
public async getAsync(): Promise<BalancesByOwner> {
const balancesByOwner: BalancesByOwner = {};
for (const tokenContractInstance of this.tokenContractInstances) {
for (const ownerAddress of this.ownerAddresses) {
let balance = await tokenContractInstance.balanceOf(ownerAddress);
balance = new BigNumber(balance);
if (_.isUndefined(balancesByOwner[ownerAddress])) {
balancesByOwner[ownerAddress] = {};
}
balancesByOwner[ownerAddress][tokenContractInstance.address] = balance;
}
private tokenContractInstances: ContractInstance[];
private ownerAddresses: string[];
constructor(tokenContractInstances: ContractInstance[], ownerAddresses: string[]) {
this.tokenContractInstances = tokenContractInstances;
this.ownerAddresses = ownerAddresses;
}
public async getAsync(): Promise<BalancesByOwner> {
const balancesByOwner: BalancesByOwner = {};
for (const tokenContractInstance of this.tokenContractInstances) {
for (const ownerAddress of this.ownerAddresses) {
let balance = await tokenContractInstance.balanceOf(ownerAddress);
balance = new BigNumber(balance);
if (_.isUndefined(balancesByOwner[ownerAddress])) {
balancesByOwner[ownerAddress] = {};
}
balancesByOwner[ownerAddress][tokenContractInstance.address] = balance;
}
}
return balancesByOwner;
}
return balancesByOwner;
}
}

View File

@@ -5,7 +5,7 @@ import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
export const crypto = {
/*
/*
* We convert types from JS to Solidity as follows:
* BigNumber -> uint256
* number -> uint8
@@ -13,26 +13,26 @@ export const crypto = {
* boolean -> bool
* valid Ethereum address -> address
*/
solSHA3(args: any[]): Buffer {
const argTypes: string[] = [];
_.each(args, (arg, i) => {
const isNumber = _.isFinite(arg);
if (isNumber) {
argTypes.push('uint8');
} else if ((arg).isBigNumber) {
argTypes.push('uint256');
args[i] = new BN(arg.toString(10), 10);
} else if (ethUtil.isValidAddress(arg)) {
argTypes.push('address');
} else if (_.isString(arg)) {
argTypes.push('string');
} else if (_.isBoolean(arg)) {
argTypes.push('bool');
} else {
throw new Error(`Unable to guess arg type: ${arg}`);
}
});
const hash = ABI.soliditySHA3(argTypes, args);
return hash;
},
solSHA3(args: any[]): Buffer {
const argTypes: string[] = [];
_.each(args, (arg, i) => {
const isNumber = _.isFinite(arg);
if (isNumber) {
argTypes.push('uint8');
} else if ((arg).isBigNumber) {
argTypes.push('uint256');
args[i] = new BN(arg.toString(10), 10);
} else if (ethUtil.isValidAddress(arg)) {
argTypes.push('address');
} else if (_.isString(arg)) {
argTypes.push('string');
} else if (_.isBoolean(arg)) {
argTypes.push('bool');
} else {
throw new Error(`Unable to guess arg type: ${arg}`);
}
});
const hash = ABI.soliditySHA3(argTypes, args);
return hash;
},
};

View File

@@ -6,163 +6,162 @@ import {Order} from './order';
import {ContractInstance} from './types';
export class ExchangeWrapper {
private exchange: ContractInstance;
constructor(exchangeContractInstance: ContractInstance) {
this.exchange = exchangeContractInstance;
}
public async fillOrderAsync(order: Order, from: string,
opts: {
fillTakerTokenAmount?: BigNumber;
shouldThrowOnInsufficientBalanceOrAllowance?: boolean;
} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
const tx = await this.exchange.fillOrder(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
params.shouldThrowOnInsufficientBalanceOrAllowance,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async cancelOrderAsync(order: Order, from: string,
opts: {cancelTakerTokenAmount?: BigNumber} = {}) {
const params = order.createCancel(opts.cancelTakerTokenAmount);
const tx = await this.exchange.cancelOrder(
params.orderAddresses,
params.orderValues,
params.cancelTakerTokenAmount,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async fillOrKillOrderAsync(order: Order, from: string,
opts: {fillTakerTokenAmount?: BigNumber} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = true;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
const tx = await this.exchange.fillOrKillOrder(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async batchFillOrdersAsync(orders: Order[], from: string,
opts: {
fillTakerTokenAmounts?: BigNumber[];
shouldThrowOnInsufficientBalanceOrAllowance?: boolean;
} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = formatters.createBatchFill(
orders, shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmounts);
const tx = await this.exchange.batchFillOrders(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmounts,
params.shouldThrowOnInsufficientBalanceOrAllowance,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async batchFillOrKillOrdersAsync(orders: Order[], from: string,
opts: {
fillTakerTokenAmounts?: BigNumber[];
} = {}) {
const params = formatters.createBatchFill(orders, undefined, opts.fillTakerTokenAmounts);
const tx = await this.exchange.batchFillOrKillOrders(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmounts,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async fillOrdersUpToAsync(orders: Order[], from: string,
opts: {fillTakerTokenAmount?: BigNumber;
private exchange: ContractInstance;
constructor(exchangeContractInstance: ContractInstance) {
this.exchange = exchangeContractInstance;
}
public async fillOrderAsync(order: Order, from: string,
opts: {
fillTakerTokenAmount?: BigNumber;
shouldThrowOnInsufficientBalanceOrAllowance?: boolean;
} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
const tx = await this.exchange.fillOrder(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
params.shouldThrowOnInsufficientBalanceOrAllowance,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async cancelOrderAsync(order: Order, from: string,
opts: {cancelTakerTokenAmount?: BigNumber} = {}) {
const params = order.createCancel(opts.cancelTakerTokenAmount);
const tx = await this.exchange.cancelOrder(
params.orderAddresses,
params.orderValues,
params.cancelTakerTokenAmount,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async fillOrKillOrderAsync(order: Order, from: string,
opts: {fillTakerTokenAmount?: BigNumber} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = true;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmount);
const tx = await this.exchange.fillOrKillOrder(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async batchFillOrdersAsync(orders: Order[], from: string,
opts: {
fillTakerTokenAmounts?: BigNumber[];
shouldThrowOnInsufficientBalanceOrAllowance?: boolean;
} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = formatters.createFillUpTo(orders,
} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = formatters.createBatchFill(
orders, shouldThrowOnInsufficientBalanceOrAllowance, opts.fillTakerTokenAmounts);
const tx = await this.exchange.batchFillOrders(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmounts,
params.shouldThrowOnInsufficientBalanceOrAllowance,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async batchFillOrKillOrdersAsync(orders: Order[], from: string,
opts: {fillTakerTokenAmounts?: BigNumber[]} = {}) {
const params = formatters.createBatchFill(orders, undefined, opts.fillTakerTokenAmounts);
const tx = await this.exchange.batchFillOrKillOrders(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmounts,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async fillOrdersUpToAsync(orders: Order[], from: string,
opts: {
fillTakerTokenAmount?: BigNumber;
shouldThrowOnInsufficientBalanceOrAllowance?: boolean;
} = {}) {
const shouldThrowOnInsufficientBalanceOrAllowance = !!opts.shouldThrowOnInsufficientBalanceOrAllowance;
const params = formatters.createFillUpTo(orders,
shouldThrowOnInsufficientBalanceOrAllowance,
opts.fillTakerTokenAmount);
const tx = await this.exchange.fillOrdersUpTo(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
params.shouldThrowOnInsufficientBalanceOrAllowance,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async batchCancelOrdersAsync(orders: Order[], from: string,
opts: {cancelTakerTokenAmounts?: BigNumber[]} = {}) {
const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts);
const tx = await this.exchange.batchCancelOrders(
params.orderAddresses,
params.orderValues,
params.cancelTakerTokenAmounts,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async getOrderHashAsync(order: Order): Promise<string> {
const shouldThrowOnInsufficientBalanceOrAllowance = false;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance);
const orderHash = await this.exchange.getOrderHash(params.orderAddresses, params.orderValues);
return orderHash;
}
public async isValidSignatureAsync(order: Order): Promise<boolean> {
const isValidSignature = await this.exchange.isValidSignature(
order.params.maker,
order.params.orderHashHex,
order.params.v,
order.params.r,
order.params.s,
);
return isValidSignature;
}
public async isRoundingErrorAsync(numerator: BigNumber, denominator: BigNumber,
target: BigNumber): Promise<boolean> {
const isRoundingError = await this.exchange.isRoundingError(numerator, denominator, target);
return isRoundingError;
}
public async getPartialAmountAsync(numerator: BigNumber, denominator: BigNumber,
target: BigNumber): Promise<BigNumber> {
const partialAmount = new BigNumber(await this.exchange.getPartialAmount(numerator, denominator, target));
return partialAmount;
}
const tx = await this.exchange.fillOrdersUpTo(
params.orderAddresses,
params.orderValues,
params.fillTakerTokenAmount,
params.shouldThrowOnInsufficientBalanceOrAllowance,
params.v,
params.r,
params.s,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async batchCancelOrdersAsync(orders: Order[], from: string,
opts: {cancelTakerTokenAmounts?: BigNumber[]} = {}) {
const params = formatters.createBatchCancel(orders, opts.cancelTakerTokenAmounts);
const tx = await this.exchange.batchCancelOrders(
params.orderAddresses,
params.orderValues,
params.cancelTakerTokenAmounts,
{from},
);
_.each(tx.logs, log => wrapLogBigNumbers(log));
return tx;
}
public async getOrderHashAsync(order: Order): Promise<string> {
const shouldThrowOnInsufficientBalanceOrAllowance = false;
const params = order.createFill(shouldThrowOnInsufficientBalanceOrAllowance);
const orderHash = await this.exchange.getOrderHash(params.orderAddresses, params.orderValues);
return orderHash;
}
public async isValidSignatureAsync(order: Order): Promise<boolean> {
const isValidSignature = await this.exchange.isValidSignature(
order.params.maker,
order.params.orderHashHex,
order.params.v,
order.params.r,
order.params.s,
);
return isValidSignature;
}
public async isRoundingErrorAsync(numerator: BigNumber, denominator: BigNumber,
target: BigNumber): Promise<boolean> {
const isRoundingError = await this.exchange.isRoundingError(numerator, denominator, target);
return isRoundingError;
}
public async getPartialAmountAsync(numerator: BigNumber, denominator: BigNumber,
target: BigNumber): Promise<BigNumber> {
const partialAmount = new BigNumber(await this.exchange.getPartialAmount(numerator, denominator, target));
return partialAmount;
}
}
function wrapLogBigNumbers(log: any): any {
const argNames = _.keys(log.args);
for (const argName of argNames) {
const isWeb3BigNumber = _.startsWith(log.args[argName].constructor.toString(), 'function BigNumber(');
if (isWeb3BigNumber) {
log.args[argName] = new BigNumber(log.args[argName]);
const argNames = _.keys(log.args);
for (const argName of argNames) {
const isWeb3BigNumber = _.startsWith(log.args[argName].constructor.toString(), 'function BigNumber(');
if (isWeb3BigNumber) {
log.args[argName] = new BigNumber(log.args[argName]);
}
}
}
}

View File

@@ -5,70 +5,73 @@ import {Order} from './order';
import {BatchCancelOrders, BatchFillOrders, FillOrdersUpTo} from './types';
export const formatters = {
createBatchFill(orders: Order[],
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
fillTakerTokenAmounts: BigNumber[] = []) {
const batchFill: BatchFillOrders = {
orderAddresses: [],
orderValues: [],
fillTakerTokenAmounts,
shouldThrowOnInsufficientBalanceOrAllowance,
v: [],
r: [],
s: [],
};
_.forEach(orders, order => {
batchFill.orderAddresses.push([order.params.maker, order.params.taker, order.params.makerToken,
createBatchFill(orders: Order[],
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
fillTakerTokenAmounts: BigNumber[] = []) {
const batchFill: BatchFillOrders = {
orderAddresses: [],
orderValues: [],
fillTakerTokenAmounts,
shouldThrowOnInsufficientBalanceOrAllowance,
v: [],
r: [],
s: [],
};
_.forEach(orders, order => {
batchFill.orderAddresses.push([order.params.maker, order.params.taker, order.params.makerToken,
order.params.takerToken, order.params.feeRecipient]);
batchFill.orderValues.push([order.params.makerTokenAmount, order.params.takerTokenAmount, order.params.makerFee,
order.params.takerFee, order.params.expirationTimestampInSec, order.params.salt]);
batchFill.v.push(order.params.v);
batchFill.r.push(order.params.r);
batchFill.s.push(order.params.s);
if (fillTakerTokenAmounts.length < orders.length) {
batchFill.fillTakerTokenAmounts.push(order.params.takerTokenAmount);
}
});
return batchFill;
},
createFillUpTo(orders: Order[],
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
fillTakerTokenAmount: BigNumber) {
const fillUpTo: FillOrdersUpTo = {
orderAddresses: [],
orderValues: [],
fillTakerTokenAmount,
shouldThrowOnInsufficientBalanceOrAllowance,
v: [],
r: [],
s: [],
};
orders.forEach(order => {
fillUpTo.orderAddresses.push([order.params.maker, order.params.taker, order.params.makerToken,
order.params.takerToken, order.params.feeRecipient]);
fillUpTo.orderValues.push([order.params.makerTokenAmount, order.params.takerTokenAmount, order.params.makerFee,
order.params.takerFee, order.params.expirationTimestampInSec, order.params.salt]);
fillUpTo.v.push(order.params.v);
fillUpTo.r.push(order.params.r);
fillUpTo.s.push(order.params.s);
});
return fillUpTo;
},
createBatchCancel(orders: Order[], cancelTakerTokenAmounts: BigNumber[] = []) {
const batchCancel: BatchCancelOrders = {
orderAddresses: [],
orderValues: [],
cancelTakerTokenAmounts,
};
orders.forEach(order => {
batchCancel.orderAddresses.push([order.params.maker, order.params.taker, order.params.makerToken,
batchFill.orderValues.push([order.params.makerTokenAmount, order.params.takerTokenAmount,
order.params.makerFee, order.params.takerFee,
order.params.expirationTimestampInSec, order.params.salt]);
batchFill.v.push(order.params.v);
batchFill.r.push(order.params.r);
batchFill.s.push(order.params.s);
if (fillTakerTokenAmounts.length < orders.length) {
batchFill.fillTakerTokenAmounts.push(order.params.takerTokenAmount);
}
});
return batchFill;
},
createFillUpTo(orders: Order[],
shouldThrowOnInsufficientBalanceOrAllowance: boolean,
fillTakerTokenAmount: BigNumber) {
const fillUpTo: FillOrdersUpTo = {
orderAddresses: [],
orderValues: [],
fillTakerTokenAmount,
shouldThrowOnInsufficientBalanceOrAllowance,
v: [],
r: [],
s: [],
};
orders.forEach(order => {
fillUpTo.orderAddresses.push([order.params.maker, order.params.taker, order.params.makerToken,
order.params.takerToken, order.params.feeRecipient]);
fillUpTo.orderValues.push([order.params.makerTokenAmount, order.params.takerTokenAmount,
order.params.makerFee, order.params.takerFee,
order.params.expirationTimestampInSec, order.params.salt]);
fillUpTo.v.push(order.params.v);
fillUpTo.r.push(order.params.r);
fillUpTo.s.push(order.params.s);
});
return fillUpTo;
},
createBatchCancel(orders: Order[], cancelTakerTokenAmounts: BigNumber[] = []) {
const batchCancel: BatchCancelOrders = {
orderAddresses: [],
orderValues: [],
cancelTakerTokenAmounts,
};
orders.forEach(order => {
batchCancel.orderAddresses.push([order.params.maker, order.params.taker, order.params.makerToken,
order.params.takerToken, order.params.feeRecipient]);
batchCancel.orderValues.push([order.params.makerTokenAmount, order.params.takerTokenAmount, order.params.makerFee,
order.params.takerFee, order.params.expirationTimestampInSec, order.params.salt]);
if (cancelTakerTokenAmounts.length < orders.length) {
batchCancel.cancelTakerTokenAmounts.push(order.params.takerTokenAmount);
}
});
return batchCancel;
},
batchCancel.orderValues.push([order.params.makerTokenAmount, order.params.takerTokenAmount,
order.params.makerFee, order.params.takerFee,
order.params.expirationTimestampInSec, order.params.salt]);
if (cancelTakerTokenAmounts.length < orders.length) {
batchCancel.cancelTakerTokenAmounts.push(order.params.takerTokenAmount);
}
});
return batchCancel;
},
};

View File

@@ -6,29 +6,29 @@ import * as Web3 from 'web3';
import {ContractInstance, TransactionDataParams} from './types';
export class MultiSigWrapper {
private multiSig: ContractInstance;
constructor(multiSigContractInstance: ContractInstance) {
this.multiSig = multiSigContractInstance;
}
public async submitTransactionAsync(destination: string, from: string,
dataParams: TransactionDataParams,
value: number = 0) {
const {name, abi, args = []} = dataParams;
const encoded = this.encodeFnArgs(name, abi, args);
return this.multiSig.submitTransaction(destination, value, encoded, {from});
}
public encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) {
const abiEntity = _.find(abi, {name}) as Web3.MethodAbi;
if (_.isUndefined(abiEntity)) {
throw new Error(`Did not find abi entry for name: ${name}`);
private multiSig: ContractInstance;
constructor(multiSigContractInstance: ContractInstance) {
this.multiSig = multiSigContractInstance;
}
public async submitTransactionAsync(destination: string, from: string,
dataParams: TransactionDataParams,
value: number = 0) {
const {name, abi, args = []} = dataParams;
const encoded = this.encodeFnArgs(name, abi, args);
return this.multiSig.submitTransaction(destination, value, encoded, {from});
}
public encodeFnArgs(name: string, abi: Web3.AbiDefinition[], args: any[]) {
const abiEntity = _.find(abi, {name}) as Web3.MethodAbi;
if (_.isUndefined(abiEntity)) {
throw new Error(`Did not find abi entry for name: ${name}`);
}
const types = _.map(abiEntity.inputs, input => input.type);
const funcSig = ethUtil.bufferToHex(ABI.methodID(name, types));
const argsData = _.map(args, arg => {
const target = _.isBoolean(arg) ? +arg : arg;
const targetBuff = ethUtil.toBuffer(target);
return ethUtil.setLengthLeft(targetBuff, 32).toString('hex');
});
return funcSig + argsData.join('');
}
const types = _.map(abiEntity.inputs, input => input.type);
const funcSig = ethUtil.bufferToHex(ABI.methodID(name, types));
const argsData = _.map(args, arg => {
const target = _.isBoolean(arg) ? +arg : arg;
const targetBuff = ethUtil.toBuffer(target);
return ethUtil.setLengthLeft(targetBuff, 32).toString('hex');
});
return funcSig + argsData.join('');
}
}

View File

@@ -12,98 +12,98 @@ import {OrderParams} from './types';
const web3: Web3 = (global as any).web3;
export class Order {
public params: OrderParams;
constructor(params: OrderParams) {
this.params = params;
}
public isValidSignature() {
const {v, r, s} = this.params;
if (_.isUndefined(v) || _.isUndefined(r) || _.isUndefined(s)) {
throw new Error('Cannot call isValidSignature on unsigned order');
public params: OrderParams;
constructor(params: OrderParams) {
this.params = params;
}
const orderHash = this.getOrderHash();
const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(orderHash));
try {
const pubKey = ethUtil.ecrecover(msgHash, v, ethUtil.toBuffer(r), ethUtil.toBuffer(s));
const recoveredAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
return recoveredAddress === this.params.maker;
} catch (err) {
return false;
public isValidSignature() {
const {v, r, s} = this.params;
if (_.isUndefined(v) || _.isUndefined(r) || _.isUndefined(s)) {
throw new Error('Cannot call isValidSignature on unsigned order');
}
const orderHash = this.getOrderHash();
const msgHash = ethUtil.hashPersonalMessage(ethUtil.toBuffer(orderHash));
try {
const pubKey = ethUtil.ecrecover(msgHash, v, ethUtil.toBuffer(r), ethUtil.toBuffer(s));
const recoveredAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
return recoveredAddress === this.params.maker;
} catch (err) {
return false;
}
}
public async signAsync() {
const orderHash = this.getOrderHash();
const signature = await promisify(web3.eth.sign)(this.params.maker, orderHash);
const {v, r, s} = ethUtil.fromRpcSig(signature);
this.params = _.assign(this.params, {
orderHashHex: orderHash,
v,
r: ethUtil.bufferToHex(r),
s: ethUtil.bufferToHex(s),
});
}
public createFill(shouldThrowOnInsufficientBalanceOrAllowance?: boolean, fillTakerTokenAmount?: BigNumber) {
const fill = {
orderAddresses: [
this.params.maker,
this.params.taker,
this.params.makerToken,
this.params.takerToken,
this.params.feeRecipient,
],
orderValues: [
this.params.makerTokenAmount,
this.params.takerTokenAmount,
this.params.makerFee,
this.params.takerFee,
this.params.expirationTimestampInSec,
this.params.salt,
],
fillTakerTokenAmount: fillTakerTokenAmount || this.params.takerTokenAmount,
shouldThrowOnInsufficientBalanceOrAllowance: !!shouldThrowOnInsufficientBalanceOrAllowance,
v: this.params.v,
r: this.params.r,
s: this.params.s,
};
return fill;
}
public createCancel(cancelTakerTokenAmount?: BigNumber) {
const cancel = {
orderAddresses: [
this.params.maker,
this.params.taker,
this.params.makerToken,
this.params.takerToken,
this.params.feeRecipient,
],
orderValues: [
this.params.makerTokenAmount,
this.params.takerTokenAmount,
this.params.makerFee,
this.params.takerFee,
this.params.expirationTimestampInSec,
this.params.salt,
],
cancelTakerTokenAmount: cancelTakerTokenAmount || this.params.takerTokenAmount,
};
return cancel;
}
private getOrderHash(): string {
const orderHash = crypto.solSHA3([
this.params.exchangeContractAddress,
this.params.maker,
this.params.taker,
this.params.makerToken,
this.params.takerToken,
this.params.feeRecipient,
this.params.makerTokenAmount,
this.params.takerTokenAmount,
this.params.makerFee,
this.params.takerFee,
this.params.expirationTimestampInSec,
this.params.salt,
]);
const orderHashHex = ethUtil.bufferToHex(orderHash);
return orderHashHex;
}
}
public async signAsync() {
const orderHash = this.getOrderHash();
const signature = await promisify(web3.eth.sign)(this.params.maker, orderHash);
const {v, r, s} = ethUtil.fromRpcSig(signature);
this.params = _.assign(this.params, {
orderHashHex: orderHash,
v,
r: ethUtil.bufferToHex(r),
s: ethUtil.bufferToHex(s),
});
}
public createFill(shouldThrowOnInsufficientBalanceOrAllowance?: boolean, fillTakerTokenAmount?: BigNumber) {
const fill = {
orderAddresses: [
this.params.maker,
this.params.taker,
this.params.makerToken,
this.params.takerToken,
this.params.feeRecipient,
],
orderValues: [
this.params.makerTokenAmount,
this.params.takerTokenAmount,
this.params.makerFee,
this.params.takerFee,
this.params.expirationTimestampInSec,
this.params.salt,
],
fillTakerTokenAmount: fillTakerTokenAmount || this.params.takerTokenAmount,
shouldThrowOnInsufficientBalanceOrAllowance: !!shouldThrowOnInsufficientBalanceOrAllowance,
v: this.params.v,
r: this.params.r,
s: this.params.s,
};
return fill;
}
public createCancel(cancelTakerTokenAmount?: BigNumber) {
const cancel = {
orderAddresses: [
this.params.maker,
this.params.taker,
this.params.makerToken,
this.params.takerToken,
this.params.feeRecipient,
],
orderValues: [
this.params.makerTokenAmount,
this.params.takerTokenAmount,
this.params.makerFee,
this.params.takerFee,
this.params.expirationTimestampInSec,
this.params.salt,
],
cancelTakerTokenAmount: cancelTakerTokenAmount || this.params.takerTokenAmount,
};
return cancel;
}
private getOrderHash(): string {
const orderHash = crypto.solSHA3([
this.params.exchangeContractAddress,
this.params.maker,
this.params.taker,
this.params.makerToken,
this.params.takerToken,
this.params.feeRecipient,
this.params.makerTokenAmount,
this.params.takerTokenAmount,
this.params.makerFee,
this.params.takerFee,
this.params.expirationTimestampInSec,
this.params.salt,
]);
const orderHashHex = ethUtil.bufferToHex(orderHash);
return orderHashHex;
}
}

View File

@@ -6,19 +6,19 @@ import {Order} from './order';
import {DefaultOrderParams, OptionalOrderParams, OrderParams} from './types';
export class OrderFactory {
private defaultOrderParams: DefaultOrderParams;
constructor(defaultOrderParams: DefaultOrderParams) {
this.defaultOrderParams = defaultOrderParams;
}
public async newSignedOrderAsync(customOrderParams: OptionalOrderParams = {}) {
const randomExpiration = new BigNumber(Math.floor((Date.now() + (Math.random() * 100000000000)) / 1000));
const orderParams: OrderParams = _.assign({}, {
expirationTimestampInSec: randomExpiration,
salt: ZeroEx.generatePseudoRandomSalt(),
taker: ZeroEx.NULL_ADDRESS,
}, this.defaultOrderParams, customOrderParams);
const order = new Order(orderParams);
await order.signAsync();
return order;
}
private defaultOrderParams: DefaultOrderParams;
constructor(defaultOrderParams: DefaultOrderParams) {
this.defaultOrderParams = defaultOrderParams;
}
public async newSignedOrderAsync(customOrderParams: OptionalOrderParams = {}) {
const randomExpiration = new BigNumber(Math.floor((Date.now() + (Math.random() * 100000000000)) / 1000));
const orderParams: OrderParams = _.assign({}, {
expirationTimestampInSec: randomExpiration,
salt: ZeroEx.generatePseudoRandomSalt(),
taker: ZeroEx.NULL_ADDRESS,
}, this.defaultOrderParams, customOrderParams);
const order = new Order(orderParams);
await order.signAsync();
return order;
}
}

View File

@@ -3,41 +3,41 @@ import 'isomorphic-fetch';
import * as truffleConf from '../truffle.js';
export class RPC {
private host: string;
private port: number;
private id: number;
constructor() {
this.host = truffleConf.networks.development.host;
this.port = truffleConf.networks.development.port;
this.id = 0;
}
public async increaseTimeAsync(time: number) {
const method = 'evm_increaseTime';
const params = [time];
const payload = this.toPayload(method, params);
return this.sendAsync(payload);
}
public async mineBlockAsync() {
const method = 'evm_mine';
const payload = this.toPayload(method);
return this.sendAsync(payload);
}
private toPayload(method: string, params: any[] = []) {
const payload = JSON.stringify({
id: this.id,
method,
params,
});
this.id++;
return payload;
}
private async sendAsync(payload: string): Promise<any> {
const opts = {
method: 'POST',
body: payload,
};
const response = await fetch(`http://${this.host}:${this.port}`, opts);
const responsePayload = await response.json();
return responsePayload;
}
private host: string;
private port: number;
private id: number;
constructor() {
this.host = truffleConf.networks.development.host;
this.port = truffleConf.networks.development.port;
this.id = 0;
}
public async increaseTimeAsync(time: number) {
const method = 'evm_increaseTime';
const params = [time];
const payload = this.toPayload(method, params);
return this.sendAsync(payload);
}
public async mineBlockAsync() {
const method = 'evm_mine';
const payload = this.toPayload(method);
return this.sendAsync(payload);
}
private toPayload(method: string, params: any[] = []) {
const payload = JSON.stringify({
id: this.id,
method,
params,
});
this.id++;
return payload;
}
private async sendAsync(payload: string): Promise<any> {
const opts = {
method: 'POST',
body: payload,
};
const response = await fetch(`http://${this.host}:${this.port}`, opts);
const responsePayload = await response.json();
return responsePayload;
}
}

View File

@@ -1,56 +1,56 @@
import {ContractInstance, Token} from './types';
export class TokenRegWrapper {
private tokenReg: ContractInstance;
constructor(tokenRegContractInstance: ContractInstance) {
this.tokenReg = tokenRegContractInstance;
}
public addTokenAsync(token: Token, from: string) {
const tx = this.tokenReg.addToken(
token.address,
token.name,
token.symbol,
token.decimals,
token.ipfsHash,
token.swarmHash,
{from},
);
return tx;
}
public async getTokenMetaDataAsync(tokenAddress: string) {
const data = await this.tokenReg.getTokenMetaData(tokenAddress);
const token: Token = {
address: data[0],
name: data[1],
symbol: data[2],
decimals: data[3].toNumber(),
ipfsHash: data[4],
swarmHash: data[5],
};
return token;
}
public async getTokenByNameAsync(tokenName: string) {
const data = await this.tokenReg.getTokenByName(tokenName);
const token: Token = {
address: data[0],
name: data[1],
symbol: data[2],
decimals: data[3].toNumber(),
ipfsHash: data[4],
swarmHash: data[5],
};
return token;
}
public async getTokenBySymbolAsync(tokenSymbol: string) {
const data = await this.tokenReg.getTokenBySymbol(tokenSymbol);
const token: Token = {
address: data[0],
name: data[1],
symbol: data[2],
decimals: data[3].toNumber(),
ipfsHash: data[4],
swarmHash: data[5],
};
return token;
}
private tokenReg: ContractInstance;
constructor(tokenRegContractInstance: ContractInstance) {
this.tokenReg = tokenRegContractInstance;
}
public addTokenAsync(token: Token, from: string) {
const tx = this.tokenReg.addToken(
token.address,
token.name,
token.symbol,
token.decimals,
token.ipfsHash,
token.swarmHash,
{from},
);
return tx;
}
public async getTokenMetaDataAsync(tokenAddress: string) {
const data = await this.tokenReg.getTokenMetaData(tokenAddress);
const token: Token = {
address: data[0],
name: data[1],
symbol: data[2],
decimals: data[3].toNumber(),
ipfsHash: data[4],
swarmHash: data[5],
};
return token;
}
public async getTokenByNameAsync(tokenName: string) {
const data = await this.tokenReg.getTokenByName(tokenName);
const token: Token = {
address: data[0],
name: data[1],
symbol: data[2],
decimals: data[3].toNumber(),
ipfsHash: data[4],
swarmHash: data[5],
};
return token;
}
public async getTokenBySymbolAsync(tokenSymbol: string) {
const data = await this.tokenReg.getTokenBySymbol(tokenSymbol);
const token: Token = {
address: data[0],
name: data[1],
symbol: data[2],
decimals: data[3].toNumber(),
ipfsHash: data[4],
swarmHash: data[5],
};
return token;
}
}

View File

@@ -2,118 +2,118 @@ import {BigNumber} from 'bignumber.js';
import * as Web3 from 'web3';
export interface BalancesByOwner {
[ownerAddress: string]: {
[tokenAddress: string]: BigNumber;
};
[ownerAddress: string]: {
[tokenAddress: string]: BigNumber;
};
}
export interface BatchFillOrders {
orderAddresses: string[][];
orderValues: BigNumber[][];
fillTakerTokenAmounts: BigNumber[];
shouldThrowOnInsufficientBalanceOrAllowance: boolean;
v: number[];
r: string[];
s: string[];
orderAddresses: string[][];
orderValues: BigNumber[][];
fillTakerTokenAmounts: BigNumber[];
shouldThrowOnInsufficientBalanceOrAllowance: boolean;
v: number[];
r: string[];
s: string[];
}
export interface FillOrdersUpTo {
orderAddresses: string[][];
orderValues: BigNumber[][];
fillTakerTokenAmount: BigNumber;
shouldThrowOnInsufficientBalanceOrAllowance: boolean;
v: number[];
r: string[];
s: string[];
orderAddresses: string[][];
orderValues: BigNumber[][];
fillTakerTokenAmount: BigNumber;
shouldThrowOnInsufficientBalanceOrAllowance: boolean;
v: number[];
r: string[];
s: string[];
}
export interface BatchCancelOrders {
orderAddresses: string[][];
orderValues: BigNumber[][];
cancelTakerTokenAmounts: BigNumber[];
orderAddresses: string[][];
orderValues: BigNumber[][];
cancelTakerTokenAmounts: BigNumber[];
}
export interface DefaultOrderParams {
exchangeContractAddress: string;
maker: string;
feeRecipient: string;
makerToken: string;
takerToken: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
makerFee: BigNumber;
takerFee: BigNumber;
exchangeContractAddress: string;
maker: string;
feeRecipient: string;
makerToken: string;
takerToken: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
makerFee: BigNumber;
takerFee: BigNumber;
}
export interface OptionalOrderParams {
exchangeContractAddress?: string;
maker?: string;
taker?: string;
feeRecipient?: string;
makerToken?: string;
takerToken?: string;
makerTokenAmount?: BigNumber;
takerTokenAmount?: BigNumber;
makerFee?: BigNumber;
takerFee?: BigNumber;
expirationTimestampInSec?: BigNumber;
exchangeContractAddress?: string;
maker?: string;
taker?: string;
feeRecipient?: string;
makerToken?: string;
takerToken?: string;
makerTokenAmount?: BigNumber;
takerTokenAmount?: BigNumber;
makerFee?: BigNumber;
takerFee?: BigNumber;
expirationTimestampInSec?: BigNumber;
}
export interface OrderParams {
exchangeContractAddress: string;
maker: string;
taker: string;
feeRecipient: string;
makerToken: string;
takerToken: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
makerFee: BigNumber;
takerFee: BigNumber;
expirationTimestampInSec: BigNumber;
salt: BigNumber;
orderHashHex?: string;
v?: number;
r?: string;
s?: string;
exchangeContractAddress: string;
maker: string;
taker: string;
feeRecipient: string;
makerToken: string;
takerToken: string;
makerTokenAmount: BigNumber;
takerTokenAmount: BigNumber;
makerFee: BigNumber;
takerFee: BigNumber;
expirationTimestampInSec: BigNumber;
salt: BigNumber;
orderHashHex?: string;
v?: number;
r?: string;
s?: string;
}
export interface TransactionDataParams {
name: string;
abi: Web3.AbiDefinition[];
args: any[];
name: string;
abi: Web3.AbiDefinition[];
args: any[];
}
export interface Token {
address?: string;
name: string;
symbol: string;
decimals: number;
ipfsHash: string;
swarmHash: string;
address?: string;
name: string;
symbol: string;
decimals: number;
ipfsHash: string;
swarmHash: string;
}
export interface MultiSigConfig {
owners: string[];
confirmationsRequired: number;
secondsRequired: number;
owners: string[];
confirmationsRequired: number;
secondsRequired: number;
}
export interface MultiSigConfigByNetwork {
[networkName: string]: MultiSigConfig;
[networkName: string]: MultiSigConfig;
}
export interface TokenInfoByNetwork {
development: Token[];
live: Token[];
development: Token[];
live: Token[];
}
// Named type aliases to improve readability
export type ContractInstance = any;
export enum ExchangeContractErrs {
ERROR_ORDER_EXPIRED,
ERROR_ORDER_FULLY_FILLED_OR_CANCELLED,
ERROR_ROUNDING_ERROR_TOO_LARGE,
ERROR_INSUFFICIENT_BALANCE_OR_ALLOWANCE,
ERROR_ORDER_EXPIRED,
ERROR_ORDER_FULLY_FILLED_OR_CANCELLED,
ERROR_ROUNDING_ERROR_TOO_LARGE,
ERROR_INSUFFICIENT_BALANCE_OR_ALLOWANCE,
}