Fix indentations
This commit is contained in:
@@ -2,5 +2,5 @@ import {Artifacts} from '../util/artifacts';
|
||||
const {Migrations} = new Artifacts(artifacts);
|
||||
|
||||
module.exports = (deployer: any) => {
|
||||
deployer.deploy(Migrations);
|
||||
deployer.deploy(Migrations);
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -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
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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('');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user