aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2018-11-12 12:09:13 +0800
committerAmir Bandeali <abandeali1@gmail.com>2018-11-28 08:09:51 +0800
commita0bc97b589db46adcc4e2275aa61022c9e224a3f (patch)
treefe56fad978bd10bb473e9f7da5bc76d78e884d76 /packages
parentd146e15ff3741dfd310b4e0b25166bb526b533f0 (diff)
downloaddexon-sol-tools-a0bc97b589db46adcc4e2275aa61022c9e224a3f.tar
dexon-sol-tools-a0bc97b589db46adcc4e2275aa61022c9e224a3f.tar.gz
dexon-sol-tools-a0bc97b589db46adcc4e2275aa61022c9e224a3f.tar.bz2
dexon-sol-tools-a0bc97b589db46adcc4e2275aa61022c9e224a3f.tar.lz
dexon-sol-tools-a0bc97b589db46adcc4e2275aa61022c9e224a3f.tar.xz
dexon-sol-tools-a0bc97b589db46adcc4e2275aa61022c9e224a3f.tar.zst
dexon-sol-tools-a0bc97b589db46adcc4e2275aa61022c9e224a3f.zip
Add initial MultiAssetProxy tests
Diffstat (limited to 'packages')
-rw-r--r--packages/contracts/package.json6
-rw-r--r--packages/contracts/src/artifacts/index.ts2
-rw-r--r--packages/contracts/test/asset_proxy/proxies.ts667
-rw-r--r--packages/contracts/tsconfig.json1
4 files changed, 485 insertions, 191 deletions
diff --git a/packages/contracts/package.json b/packages/contracts/package.json
index 25445c4f8..a6380a467 100644
--- a/packages/contracts/package.json
+++ b/packages/contracts/package.json
@@ -19,7 +19,8 @@
"test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov",
"test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
"test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
- "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
+ "run_mocha":
+ "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
"compile": "sol-compiler --contracts-dir contracts",
"clean": "shx rm -rf lib generated-artifacts generated-wrappers",
"generate_contract_wrappers": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output generated-wrappers --backend ethers",
@@ -32,7 +33,8 @@
"lint-contracts": "solhint contracts/**/**/**/**/*.sol"
},
"config": {
- "abis": "generated-artifacts/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Token|ERC20Proxy|ERC721Token|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|Whitelist|WETH9|ZRXToken).json"
+ "abis":
+ "generated-artifacts/@(AssetProxyOwner|DummyERC20Token|DummyERC721Receiver|DummyERC721Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Token|ERC20Proxy|ERC721Token|ERC721Proxy|Forwarder|Exchange|ExchangeWrapper|IAssetData|IAssetProxy|InvalidERC721Receiver|MixinAuthorizable|MultiAssetProxy|MultiSigWallet|MultiSigWalletWithTimeLock|OrderValidator|ReentrantERC20Token|TestAssetProxyOwner|TestAssetProxyDispatcher|TestConstants|TestExchangeInternals|TestLibBytes|TestLibs|TestSignatureValidator|TestStaticCallReceiver|Validator|Wallet|Whitelist|WETH9|ZRXToken).json"
},
"repository": {
"type": "git",
diff --git a/packages/contracts/src/artifacts/index.ts b/packages/contracts/src/artifacts/index.ts
index c30972a91..97c1b6209 100644
--- a/packages/contracts/src/artifacts/index.ts
+++ b/packages/contracts/src/artifacts/index.ts
@@ -19,6 +19,7 @@ import * as InvalidERC721Receiver from '../../generated-artifacts/InvalidERC721R
import * as IValidator from '../../generated-artifacts/IValidator.json';
import * as IWallet from '../../generated-artifacts/IWallet.json';
import * as MixinAuthorizable from '../../generated-artifacts/MixinAuthorizable.json';
+import * as MultiAssetProxy from '../../generated-artifacts/MultiAssetProxy.json';
import * as MultiSigWallet from '../../generated-artifacts/MultiSigWallet.json';
import * as MultiSigWalletWithTimeLock from '../../generated-artifacts/MultiSigWalletWithTimeLock.json';
import * as OrderValidator from '../../generated-artifacts/OrderValidator.json';
@@ -57,6 +58,7 @@ export const artifacts = {
IWallet: IWallet as ContractArtifact,
InvalidERC721Receiver: InvalidERC721Receiver as ContractArtifact,
MixinAuthorizable: MixinAuthorizable as ContractArtifact,
+ MultiAssetProxy: MultiAssetProxy as ContractArtifact,
MultiSigWallet: MultiSigWallet as ContractArtifact,
MultiSigWalletWithTimeLock: MultiSigWalletWithTimeLock as ContractArtifact,
OrderValidator: OrderValidator as ContractArtifact,
diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts
index b8305993e..94ea408f5 100644
--- a/packages/contracts/test/asset_proxy/proxies.ts
+++ b/packages/contracts/test/asset_proxy/proxies.ts
@@ -12,7 +12,9 @@ import { DummyMultipleReturnERC20TokenContract } from '../../generated-wrappers/
import { DummyNoReturnERC20TokenContract } from '../../generated-wrappers/dummy_no_return_erc20_token';
import { ERC20ProxyContract } from '../../generated-wrappers/erc20_proxy';
import { ERC721ProxyContract } from '../../generated-wrappers/erc721_proxy';
+import { IAssetDataContract } from '../../generated-wrappers/i_asset_data';
import { IAssetProxyContract } from '../../generated-wrappers/i_asset_proxy';
+import { MultiAssetProxyContract } from '../../generated-wrappers/multi_asset_proxy';
import { artifacts } from '../../src/artifacts';
import { expectTransactionFailedAsync, expectTransactionFailedWithoutReasonAsync } from '../utils/assertions';
import { chaiSetup } from '../utils/chai_setup';
@@ -30,26 +32,35 @@ const assetProxyInterface = new IAssetProxyContract(
constants.NULL_ADDRESS,
provider,
);
+const assetDataInterface = new IAssetDataContract(
+ artifacts.IAssetData.compilerOutput.abi,
+ constants.NULL_ADDRESS,
+ provider,
+);
// tslint:disable:no-unnecessary-type-assertion
-describe('Asset Transfer Proxies', () => {
+describe.only('Asset Transfer Proxies', () => {
let owner: string;
let notAuthorized: string;
- let exchangeAddress: string;
- let makerAddress: string;
- let takerAddress: string;
+ let authorized: string;
+ let fromAddress: string;
+ let toAddress: string;
- let zrxToken: DummyERC20TokenContract;
- let erc721Token: DummyERC721TokenContract;
+ let erc20TokenA: DummyERC20TokenContract;
+ let erc20TokenB: DummyERC20TokenContract;
+ let erc721TokenA: DummyERC721TokenContract;
+ let erc721TokenB: DummyERC721TokenContract;
let erc721Receiver: DummyERC721ReceiverContract;
let erc20Proxy: ERC20ProxyContract;
let erc721Proxy: ERC721ProxyContract;
let noReturnErc20Token: DummyNoReturnERC20TokenContract;
let multipleReturnErc20Token: DummyMultipleReturnERC20TokenContract;
+ let multiAssetProxy: MultiAssetProxyContract;
let erc20Wrapper: ERC20Wrapper;
let erc721Wrapper: ERC721Wrapper;
- let erc721MakerTokenId: BigNumber;
+ let erc721AFromTokenId: BigNumber;
+ let erc721BFromTokenId: BigNumber;
before(async () => {
await blockchainLifecycle.startAsync();
@@ -59,41 +70,73 @@ describe('Asset Transfer Proxies', () => {
});
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
- const usedAddresses = ([owner, notAuthorized, exchangeAddress, makerAddress, takerAddress] = _.slice(
- accounts,
- 0,
- 5,
- ));
+ const usedAddresses = ([owner, notAuthorized, authorized, fromAddress, toAddress] = _.slice(accounts, 0, 5));
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
- const numDummyErc20ToDeploy = 1;
- [zrxToken] = await erc20Wrapper.deployDummyTokensAsync(numDummyErc20ToDeploy, constants.DUMMY_TOKEN_DECIMALS);
+ // Deploy AssetProxies
erc20Proxy = await erc20Wrapper.deployProxyAsync();
- await erc20Wrapper.setBalancesAndAllowancesAsync();
+ erc721Proxy = await erc721Wrapper.deployProxyAsync();
+ multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
+ artifacts.MultiAssetProxy,
+ provider,
+ txDefaults,
+ );
+
+ // Configure ERC20Proxy
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeAddress, {
+ await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
+ from: owner,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await erc20Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
- [erc721Token] = await erc721Wrapper.deployDummyTokensAsync();
- erc721Proxy = await erc721Wrapper.deployProxyAsync();
- await erc721Wrapper.setBalancesAndAllowancesAsync();
- const erc721Balances = await erc721Wrapper.getBalancesAsync();
- erc721MakerTokenId = erc721Balances[makerAddress][erc721Token.address][0];
+ // Configure ERC721Proxy
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(exchangeAddress, {
+ await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
from: owner,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
- erc721Receiver = await DummyERC721ReceiverContract.deployFrom0xArtifactAsync(
- artifacts.DummyERC721Receiver,
- provider,
- txDefaults,
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await erc721Proxy.addAuthorizedAddress.sendTransactionAsync(multiAssetProxy.address, {
+ from: owner,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+
+ // Configure MultiAssetProxy
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await multiAssetProxy.addAuthorizedAddress.sendTransactionAsync(authorized, {
+ from: owner,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, {
+ from: owner,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await multiAssetProxy.registerAssetProxy.sendTransactionAsync(erc721Proxy.address, {
+ from: owner,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+
+ // Deploy and configure ERC20 tokens
+ const numDummyErc20ToDeploy = 2;
+ [erc20TokenA, erc20TokenB] = await erc20Wrapper.deployDummyTokensAsync(
+ numDummyErc20ToDeploy,
+ constants.DUMMY_TOKEN_DECIMALS,
);
noReturnErc20Token = await DummyNoReturnERC20TokenContract.deployFrom0xArtifactAsync(
artifacts.DummyNoReturnERC20Token,
@@ -104,30 +147,32 @@ describe('Asset Transfer Proxies', () => {
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
);
+ multipleReturnErc20Token = await DummyMultipleReturnERC20TokenContract.deployFrom0xArtifactAsync(
+ artifacts.DummyMultipleReturnERC20Token,
+ provider,
+ txDefaults,
+ constants.DUMMY_TOKEN_NAME,
+ constants.DUMMY_TOKEN_SYMBOL,
+ constants.DUMMY_TOKEN_DECIMALS,
+ constants.DUMMY_TOKEN_TOTAL_SUPPLY,
+ );
+
+ await erc20Wrapper.setBalancesAndAllowancesAsync();
await web3Wrapper.awaitTransactionSuccessAsync(
- await noReturnErc20Token.setBalance.sendTransactionAsync(makerAddress, constants.INITIAL_ERC20_BALANCE),
+ await noReturnErc20Token.setBalance.sendTransactionAsync(fromAddress, constants.INITIAL_ERC20_BALANCE),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await noReturnErc20Token.approve.sendTransactionAsync(
erc20Proxy.address,
constants.INITIAL_ERC20_ALLOWANCE,
- { from: makerAddress },
+ { from: fromAddress },
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
- multipleReturnErc20Token = await DummyMultipleReturnERC20TokenContract.deployFrom0xArtifactAsync(
- artifacts.DummyMultipleReturnERC20Token,
- provider,
- txDefaults,
- constants.DUMMY_TOKEN_NAME,
- constants.DUMMY_TOKEN_SYMBOL,
- constants.DUMMY_TOKEN_DECIMALS,
- constants.DUMMY_TOKEN_TOTAL_SUPPLY,
- );
await web3Wrapper.awaitTransactionSuccessAsync(
await multipleReturnErc20Token.setBalance.sendTransactionAsync(
- makerAddress,
+ fromAddress,
constants.INITIAL_ERC20_BALANCE,
),
constants.AWAIT_TRANSACTION_MINED_MS,
@@ -136,10 +181,23 @@ describe('Asset Transfer Proxies', () => {
await multipleReturnErc20Token.approve.sendTransactionAsync(
erc20Proxy.address,
constants.INITIAL_ERC20_ALLOWANCE,
- { from: makerAddress },
+ { from: fromAddress },
),
constants.AWAIT_TRANSACTION_MINED_MS,
);
+
+ // Deploy and configure ERC721 tokens and receiver
+ [erc721TokenA, erc721TokenB] = await erc721Wrapper.deployDummyTokensAsync();
+ erc721Receiver = await DummyERC721ReceiverContract.deployFrom0xArtifactAsync(
+ artifacts.DummyERC721Receiver,
+ provider,
+ txDefaults,
+ );
+
+ await erc721Wrapper.setBalancesAndAllowancesAsync();
+ const erc721Balances = await erc721Wrapper.getBalancesAsync();
+ erc721AFromTokenId = erc721Balances[fromAddress][erc721TokenA.address][0];
+ erc721BFromTokenId = erc721Balances[fromAddress][erc721TokenB.address][0];
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -147,7 +205,8 @@ describe('Asset Transfer Proxies', () => {
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
- describe('Transfer Proxy - ERC20', () => {
+
+ describe('ERC20Proxy', () => {
it('should revert if undefined function is called', async () => {
const undefinedSelector = '0x01020304';
await expectTransactionFailedWithoutReasonAsync(
@@ -159,141 +218,146 @@ describe('Asset Transfer Proxies', () => {
}),
);
});
+ it('should have an id of 0xf47261b0', async () => {
+ const proxyId = await erc20Proxy.getProxyId.callAsync();
+ const expectedProxyId = '0xf47261b0';
+ expect(proxyId).to.equal(expectedProxyId);
+ });
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
// Construct ERC20 asset data
- const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- // Perform a transfer from makerAddress to takerAddress
+ const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
+ // Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: erc20Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(amount),
+ expect(newBalances[fromAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[fromAddress][erc20TokenA.address].minus(amount),
);
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].add(amount),
+ expect(newBalances[toAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[toAddress][erc20TokenA.address].add(amount),
);
});
it('should successfully transfer tokens that do not return a value', async () => {
// Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address);
- // Perform a transfer from makerAddress to takerAddress
- const initialMakerBalance = await noReturnErc20Token.balanceOf.callAsync(makerAddress);
- const initialTakerBalance = await noReturnErc20Token.balanceOf.callAsync(takerAddress);
+ // Perform a transfer from fromAddress to toAddress
+ const initialFromBalance = await noReturnErc20Token.balanceOf.callAsync(fromAddress);
+ const initialToBalance = await noReturnErc20Token.balanceOf.callAsync(toAddress);
const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: erc20Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
- const newMakerBalance = await noReturnErc20Token.balanceOf.callAsync(makerAddress);
- const newTakerBalance = await noReturnErc20Token.balanceOf.callAsync(takerAddress);
- expect(newMakerBalance).to.be.bignumber.equal(initialMakerBalance.minus(amount));
- expect(newTakerBalance).to.be.bignumber.equal(initialTakerBalance.plus(amount));
+ const newFromBalance = await noReturnErc20Token.balanceOf.callAsync(fromAddress);
+ const newToBalance = await noReturnErc20Token.balanceOf.callAsync(toAddress);
+ expect(newFromBalance).to.be.bignumber.equal(initialFromBalance.minus(amount));
+ expect(newToBalance).to.be.bignumber.equal(initialToBalance.plus(amount));
});
it('should successfully transfer tokens and ignore extra assetData', async () => {
// Construct ERC20 asset data
const extraData = '0102030405060708';
- const encodedAssetData = `${assetDataUtils.encodeERC20AssetData(zrxToken.address)}${extraData}`;
- // Perform a transfer from makerAddress to takerAddress
+ const encodedAssetData = `${assetDataUtils.encodeERC20AssetData(erc20TokenA.address)}${extraData}`;
+ // Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: erc20Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address].minus(amount),
+ expect(newBalances[fromAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[fromAddress][erc20TokenA.address].minus(amount),
);
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address].add(amount),
+ expect(newBalances[toAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[toAddress][erc20TokenA.address].add(amount),
);
});
it('should do nothing if transferring 0 amount of a token', async () => {
// Construct ERC20 asset data
- const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- // Perform a transfer from makerAddress to takerAddress
+ const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
+ // Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: erc20Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
const newBalances = await erc20Wrapper.getBalancesAsync();
- expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[makerAddress][zrxToken.address],
+ expect(newBalances[fromAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[fromAddress][erc20TokenA.address],
);
- expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
- erc20Balances[takerAddress][zrxToken.address],
+ expect(newBalances[toAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[toAddress][erc20TokenA.address],
);
});
- it('should throw if allowances are too low', async () => {
+ it('should revert if allowances are too low', async () => {
// Construct ERC20 asset data
- const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
+ const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
// Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0);
const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
- await zrxToken.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
- from: makerAddress,
+ await erc20TokenA.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
+ from: fromAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
@@ -303,7 +367,7 @@ describe('Asset Transfer Proxies', () => {
web3Wrapper.sendTransactionAsync({
to: erc20Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
RevertReason.TransferFailed,
);
@@ -311,7 +375,7 @@ describe('Asset Transfer Proxies', () => {
expect(newBalances).to.deep.equal(erc20Balances);
});
- it('should throw if allowances are too low and token does not return a value', async () => {
+ it('should revert if allowances are too low and token does not return a value', async () => {
// Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(noReturnErc20Token.address);
// Create allowance less than transfer amount. Set allowance on proxy.
@@ -319,42 +383,42 @@ describe('Asset Transfer Proxies', () => {
const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await noReturnErc20Token.approve.sendTransactionAsync(erc20Proxy.address, allowance, {
- from: makerAddress,
+ from: fromAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
- const initialMakerBalance = await noReturnErc20Token.balanceOf.callAsync(makerAddress);
- const initialTakerBalance = await noReturnErc20Token.balanceOf.callAsync(takerAddress);
+ const initialFromBalance = await noReturnErc20Token.balanceOf.callAsync(fromAddress);
+ const initialToBalance = await noReturnErc20Token.balanceOf.callAsync(toAddress);
// Perform a transfer; expect this to fail.
await expectTransactionFailedAsync(
web3Wrapper.sendTransactionAsync({
to: erc20Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
RevertReason.TransferFailed,
);
- const newMakerBalance = await noReturnErc20Token.balanceOf.callAsync(makerAddress);
- const newTakerBalance = await noReturnErc20Token.balanceOf.callAsync(takerAddress);
- expect(newMakerBalance).to.be.bignumber.equal(initialMakerBalance);
- expect(newTakerBalance).to.be.bignumber.equal(initialTakerBalance);
+ const newFromBalance = await noReturnErc20Token.balanceOf.callAsync(fromAddress);
+ const newToBalance = await noReturnErc20Token.balanceOf.callAsync(toAddress);
+ expect(newFromBalance).to.be.bignumber.equal(initialFromBalance);
+ expect(newToBalance).to.be.bignumber.equal(initialToBalance);
});
- it('should throw if requesting address is not authorized', async () => {
+ it('should revert if caller is not authorized', async () => {
// Construct ERC20 asset data
- const encodedAssetData = assetDataUtils.encodeERC20AssetData(zrxToken.address);
- // Perform a transfer from makerAddress to takerAddress
+ const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
+ // Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
const erc20Balances = await erc20Wrapper.getBalancesAsync();
@@ -370,42 +434,36 @@ describe('Asset Transfer Proxies', () => {
expect(newBalances).to.deep.equal(erc20Balances);
});
- it('should throw if token returns more than 32 bytes', async () => {
+ it('should revert if token returns more than 32 bytes', async () => {
// Construct ERC20 asset data
const encodedAssetData = assetDataUtils.encodeERC20AssetData(multipleReturnErc20Token.address);
const amount = new BigNumber(10);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
- const initialMakerBalance = await multipleReturnErc20Token.balanceOf.callAsync(makerAddress);
- const initialTakerBalance = await multipleReturnErc20Token.balanceOf.callAsync(takerAddress);
+ const initialFromBalance = await multipleReturnErc20Token.balanceOf.callAsync(fromAddress);
+ const initialToBalance = await multipleReturnErc20Token.balanceOf.callAsync(toAddress);
// Perform a transfer; expect this to fail.
await expectTransactionFailedAsync(
web3Wrapper.sendTransactionAsync({
to: erc20Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
RevertReason.TransferFailed,
);
- const newMakerBalance = await multipleReturnErc20Token.balanceOf.callAsync(makerAddress);
- const newTakerBalance = await multipleReturnErc20Token.balanceOf.callAsync(takerAddress);
- expect(newMakerBalance).to.be.bignumber.equal(initialMakerBalance);
- expect(newTakerBalance).to.be.bignumber.equal(initialTakerBalance);
+ const newFromBalance = await multipleReturnErc20Token.balanceOf.callAsync(fromAddress);
+ const newToBalance = await multipleReturnErc20Token.balanceOf.callAsync(toAddress);
+ expect(newFromBalance).to.be.bignumber.equal(initialFromBalance);
+ expect(newToBalance).to.be.bignumber.equal(initialToBalance);
});
});
-
- it('should have an id of 0xf47261b0', async () => {
- const proxyId = await erc20Proxy.getProxyId.callAsync();
- const expectedProxyId = '0xf47261b0';
- expect(proxyId).to.equal(expectedProxyId);
- });
});
- describe('Transfer Proxy - ERC721', () => {
+ describe('ERC721Proxy', () => {
it('should revert if undefined function is called', async () => {
const undefinedSelector = '0x01020304';
await expectTransactionFailedWithoutReasonAsync(
@@ -417,76 +475,81 @@ describe('Asset Transfer Proxies', () => {
}),
);
});
+ it('should have an id of 0x02571792', async () => {
+ const proxyId = await erc721Proxy.getProxyId.callAsync();
+ const expectedProxyId = '0x02571792';
+ expect(proxyId).to.equal(expectedProxyId);
+ });
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
// Construct ERC721 asset data
- const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
+ const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
- const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(ownerMakerAsset).to.be.equal(makerAddress);
- // Perform a transfer from makerAddress to takerAddress
+ const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset).to.be.equal(fromAddress);
+ // Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(1);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: erc721Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
- const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress);
+ const newOwnerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(newOwnerFromAsset).to.be.bignumber.equal(toAddress);
});
it('should successfully transfer tokens and ignore extra assetData', async () => {
// Construct ERC721 asset data
const extraData = '0102030405060708';
const encodedAssetData = `${assetDataUtils.encodeERC721AssetData(
- erc721Token.address,
- erc721MakerTokenId,
+ erc721TokenA.address,
+ erc721AFromTokenId,
)}${extraData}`;
// Verify pre-condition
- const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(ownerMakerAsset).to.be.equal(makerAddress);
- // Perform a transfer from makerAddress to takerAddress
+ const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset).to.be.equal(fromAddress);
+ // Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(1);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await web3Wrapper.awaitTransactionSuccessAsync(
await web3Wrapper.sendTransactionAsync({
to: erc721Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
// Verify transfer was successful
- const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress);
+ const newOwnerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(newOwnerFromAsset).to.be.bignumber.equal(toAddress);
});
it('should not call onERC721Received when transferring to a smart contract', async () => {
// Construct ERC721 asset data
- const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
+ const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
- const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(ownerMakerAsset).to.be.equal(makerAddress);
- // Perform a transfer from makerAddress to takerAddress
+ const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset).to.be.equal(fromAddress);
+ // Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(1);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
+ fromAddress,
erc721Receiver.address,
amount,
);
@@ -495,79 +558,79 @@ describe('Asset Transfer Proxies', () => {
await web3Wrapper.sendTransactionAsync({
to: erc721Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
gas: constants.MAX_TRANSFER_FROM_GAS,
}),
);
// Verify that no log was emitted by erc721 receiver
expect(tx.logs.length).to.be.equal(1);
// Verify transfer was successful
- const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address);
+ const newOwnerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(newOwnerFromAsset).to.be.bignumber.equal(erc721Receiver.address);
});
- it('should throw if transferring 0 amount of a token', async () => {
+ it('should revert if transferring 0 amount of a token', async () => {
// Construct ERC721 asset data
- const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
+ const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
- const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(ownerMakerAsset).to.be.equal(makerAddress);
- // Perform a transfer from makerAddress to takerAddress
+ const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset).to.be.equal(fromAddress);
+ // Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(0);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await expectTransactionFailedAsync(
web3Wrapper.sendTransactionAsync({
to: erc721Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
RevertReason.InvalidAmount,
);
- const newOwner = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(newOwner).to.be.equal(ownerMakerAsset);
+ const newOwner = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(newOwner).to.be.equal(ownerFromAsset);
});
- it('should throw if transferring > 1 amount of a token', async () => {
+ it('should revert if transferring > 1 amount of a token', async () => {
// Construct ERC721 asset data
- const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
+ const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
- const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(ownerMakerAsset).to.be.equal(makerAddress);
- // Perform a transfer from makerAddress to takerAddress
+ const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset).to.be.equal(fromAddress);
+ // Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(500);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await expectTransactionFailedAsync(
web3Wrapper.sendTransactionAsync({
to: erc721Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
RevertReason.InvalidAmount,
);
- const newOwner = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(newOwner).to.be.equal(ownerMakerAsset);
+ const newOwner = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(newOwner).to.be.equal(ownerFromAsset);
});
- it('should throw if allowances are too low', async () => {
+ it('should revert if allowances are too low', async () => {
// Construct ERC721 asset data
- const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
+ const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
- const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(ownerMakerAsset).to.be.equal(makerAddress);
- // Remove transfer approval for makerAddress.
+ const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset).to.be.equal(fromAddress);
+ // Remove transfer approval for fromAddress.
await web3Wrapper.awaitTransactionSuccessAsync(
- await erc721Token.approve.sendTransactionAsync(constants.NULL_ADDRESS, erc721MakerTokenId, {
- from: makerAddress,
+ await erc721TokenA.approve.sendTransactionAsync(constants.NULL_ADDRESS, erc721AFromTokenId, {
+ from: fromAddress,
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
@@ -575,34 +638,34 @@ describe('Asset Transfer Proxies', () => {
const amount = new BigNumber(1);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await expectTransactionFailedAsync(
web3Wrapper.sendTransactionAsync({
to: erc721Proxy.address,
data,
- from: exchangeAddress,
+ from: authorized,
}),
RevertReason.TransferFailed,
);
- const newOwner = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(newOwner).to.be.equal(ownerMakerAsset);
+ const newOwner = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(newOwner).to.be.equal(ownerFromAsset);
});
- it('should throw if requesting address is not authorized', async () => {
+ it('should revert if caller is not authorized', async () => {
// Construct ERC721 asset data
- const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
+ const encodedAssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
- const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(ownerMakerAsset).to.be.equal(makerAddress);
- // Perform a transfer from makerAddress to takerAddress
+ const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset).to.be.equal(fromAddress);
+ // Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(1);
const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
encodedAssetData,
- makerAddress,
- takerAddress,
+ fromAddress,
+ toAddress,
amount,
);
await expectTransactionFailedAsync(
@@ -613,16 +676,242 @@ describe('Asset Transfer Proxies', () => {
}),
RevertReason.SenderNotAuthorized,
);
- const newOwner = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
- expect(newOwner).to.be.equal(ownerMakerAsset);
+ const newOwner = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(newOwner).to.be.equal(ownerFromAsset);
});
});
-
- it('should have an id of 0x02571792', async () => {
- const proxyId = await erc721Proxy.getProxyId.callAsync();
- const expectedProxyId = '0x02571792';
+ });
+ describe.only('MultiAssetProxy', () => {
+ it('should revert if undefined function is called', async () => {
+ const undefinedSelector = '0x01020304';
+ await expectTransactionFailedWithoutReasonAsync(
+ web3Wrapper.sendTransactionAsync({
+ from: owner,
+ to: multiAssetProxy.address,
+ value: constants.ZERO_AMOUNT,
+ data: undefinedSelector,
+ }),
+ );
+ });
+ it('should have an id of 0x94cfcdd7', async () => {
+ const proxyId = await multiAssetProxy.getProxyId.callAsync();
+ const expectedProxyId = '0x94cfcdd7';
expect(proxyId).to.equal(expectedProxyId);
});
+ describe('transferFrom', () => {
+ it('should transfer a single ERC20 token', async () => {
+ const inputAmount = new BigNumber(1);
+ const erc20Amount = new BigNumber(10);
+ const erc20AssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
+ const amounts = [erc20Amount];
+ const nestedAssetData = [erc20AssetData];
+ const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ assetData,
+ fromAddress,
+ toAddress,
+ inputAmount,
+ );
+ const erc20Balances = await erc20Wrapper.getBalancesAsync();
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await web3Wrapper.sendTransactionAsync({
+ to: multiAssetProxy.address,
+ data,
+ from: authorized,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ // Verify transfer was successful
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+ const totalAmount = inputAmount.times(erc20Amount);
+ expect(newBalances[fromAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[fromAddress][erc20TokenA.address].minus(totalAmount),
+ );
+ expect(newBalances[toAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[toAddress][erc20TokenA.address].add(totalAmount),
+ );
+ });
+ it('should successfully transfer multiple of the same ERC20 token', async () => {
+ const inputAmount = new BigNumber(1);
+ const erc20Amount1 = new BigNumber(10);
+ const erc20Amount2 = new BigNumber(20);
+ const erc20AssetData1 = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
+ const erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
+ const amounts = [erc20Amount1, erc20Amount2];
+ const nestedAssetData = [erc20AssetData1, erc20AssetData2];
+ const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ assetData,
+ fromAddress,
+ toAddress,
+ inputAmount,
+ );
+ const erc20Balances = await erc20Wrapper.getBalancesAsync();
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await web3Wrapper.sendTransactionAsync({
+ to: multiAssetProxy.address,
+ data,
+ from: authorized,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ // Verify transfer was successful
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+ const totalAmount = inputAmount.times(erc20Amount1).plus(inputAmount.times(erc20Amount2));
+ expect(newBalances[fromAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[fromAddress][erc20TokenA.address].minus(totalAmount),
+ );
+ expect(newBalances[toAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[toAddress][erc20TokenA.address].add(totalAmount),
+ );
+ });
+ it('should successfully transfer multiple different ERC20 tokens', async () => {
+ const inputAmount = new BigNumber(1);
+ const erc20Amount1 = new BigNumber(10);
+ const erc20Amount2 = new BigNumber(20);
+ const erc20AssetData1 = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
+ const erc20AssetData2 = assetDataUtils.encodeERC20AssetData(erc20TokenB.address);
+ const amounts = [erc20Amount1, erc20Amount2];
+ const nestedAssetData = [erc20AssetData1, erc20AssetData2];
+ const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ assetData,
+ fromAddress,
+ toAddress,
+ inputAmount,
+ );
+ const erc20Balances = await erc20Wrapper.getBalancesAsync();
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await web3Wrapper.sendTransactionAsync({
+ to: multiAssetProxy.address,
+ data,
+ from: authorized,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ // Verify transfer was successful
+ const newBalances = await erc20Wrapper.getBalancesAsync();
+ const totalErc20AAmount = inputAmount.times(erc20Amount1);
+ const totalErc20BAmount = inputAmount.times(erc20Amount2);
+ expect(newBalances[fromAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[fromAddress][erc20TokenA.address].minus(totalErc20AAmount),
+ );
+ expect(newBalances[toAddress][erc20TokenA.address]).to.be.bignumber.equal(
+ erc20Balances[toAddress][erc20TokenA.address].add(totalErc20AAmount),
+ );
+ expect(newBalances[fromAddress][erc20TokenB.address]).to.be.bignumber.equal(
+ erc20Balances[fromAddress][erc20TokenB.address].minus(totalErc20BAmount),
+ );
+ expect(newBalances[toAddress][erc20TokenB.address]).to.be.bignumber.equal(
+ erc20Balances[toAddress][erc20TokenB.address].add(totalErc20BAmount),
+ );
+ });
+ it('should transfer a single ERC721 token', async () => {
+ const inputAmount = new BigNumber(1);
+ const erc721Amount = new BigNumber(1);
+ const erc721AssetData = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
+ const amounts = [erc721Amount];
+ const nestedAssetData = [erc721AssetData];
+ const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ assetData,
+ fromAddress,
+ toAddress,
+ inputAmount,
+ );
+ const ownerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset).to.be.equal(fromAddress);
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await web3Wrapper.sendTransactionAsync({
+ to: multiAssetProxy.address,
+ data,
+ from: authorized,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ const newOwnerFromAsset = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(newOwnerFromAsset).to.be.equal(toAddress);
+ });
+ it('should successfully transfer multiple of the same ERC721 token', async () => {
+ const erc721Balances = await erc721Wrapper.getBalancesAsync();
+ const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
+ const erc721AssetData1 = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
+ const erc721AssetData2 = assetDataUtils.encodeERC721AssetData(
+ erc721TokenA.address,
+ erc721AFromTokenId2,
+ );
+ const inputAmount = new BigNumber(1);
+ const erc721Amount = new BigNumber(1);
+ const amounts = [erc721Amount, erc721Amount];
+ const nestedAssetData = [erc721AssetData1, erc721AssetData2];
+ const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ assetData,
+ fromAddress,
+ toAddress,
+ inputAmount,
+ );
+ const ownerFromAsset1 = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset1).to.be.equal(fromAddress);
+ const ownerFromAsset2 = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId2);
+ expect(ownerFromAsset2).to.be.equal(fromAddress);
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await web3Wrapper.sendTransactionAsync({
+ to: multiAssetProxy.address,
+ data,
+ from: authorized,
+ gas: constants.MAX_TRANSFER_FROM_GAS,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ const newOwnerFromAsset1 = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ const newOwnerFromAsset2 = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId2);
+ expect(newOwnerFromAsset1).to.be.equal(toAddress);
+ expect(newOwnerFromAsset2).to.be.equal(toAddress);
+ });
+ it('should successfully transfer multiple different ERC721 tokens', async () => {
+ const erc721AssetData1 = assetDataUtils.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
+ const erc721AssetData2 = assetDataUtils.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId);
+ const inputAmount = new BigNumber(1);
+ const erc721Amount = new BigNumber(1);
+ const amounts = [erc721Amount, erc721Amount];
+ const nestedAssetData = [erc721AssetData1, erc721AssetData2];
+ const assetData = assetDataInterface.MultiAsset.getABIEncodedTransactionData(amounts, nestedAssetData);
+ const data = assetProxyInterface.transferFrom.getABIEncodedTransactionData(
+ assetData,
+ fromAddress,
+ toAddress,
+ inputAmount,
+ );
+ const ownerFromAsset1 = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ expect(ownerFromAsset1).to.be.equal(fromAddress);
+ const ownerFromAsset2 = await erc721TokenB.ownerOf.callAsync(erc721BFromTokenId);
+ expect(ownerFromAsset2).to.be.equal(fromAddress);
+ await web3Wrapper.awaitTransactionSuccessAsync(
+ await web3Wrapper.sendTransactionAsync({
+ to: multiAssetProxy.address,
+ data,
+ from: authorized,
+ gas: constants.MAX_TRANSFER_FROM_GAS,
+ }),
+ constants.AWAIT_TRANSACTION_MINED_MS,
+ );
+ const newOwnerFromAsset1 = await erc721TokenA.ownerOf.callAsync(erc721AFromTokenId);
+ const newOwnerFromAsset2 = await erc721TokenB.ownerOf.callAsync(erc721BFromTokenId);
+ expect(newOwnerFromAsset1).to.be.equal(toAddress);
+ expect(newOwnerFromAsset2).to.be.equal(toAddress);
+ });
+ it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => {});
+ it('should successfully transfer tokens and ignore extra assetData', async () => {});
+ it('should successfully transfer correct amounts when the `amount` > 1', async () => {});
+ it('should revert if a single transfer fails', async () => {});
+ it('should revert if an AssetProxy is not registered', async () => {});
+ it('should revert if the length of `amounts` does not match the length of `nestedAssetData`', async () => {});
+ it('should revert if amounts multiplication results in an overflow', async () => {});
+ it('should revert if an element of `nestedAssetData` is < 4 bytes long', async () => {});
+ it('should revert with the same reason as the called AssetProxy', async () => {});
+ it('should revert if caller is not authorized', async () => {});
+ });
});
});
// tslint:enable:no-unnecessary-type-assertion
diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json
index 8b29365cc..e0f85079a 100644
--- a/packages/contracts/tsconfig.json
+++ b/packages/contracts/tsconfig.json
@@ -26,6 +26,7 @@
"./generated-artifacts/IWallet.json",
"./generated-artifacts/InvalidERC721Receiver.json",
"./generated-artifacts/MixinAuthorizable.json",
+ "./generated-artifacts/MultiAssetProxy.json",
"./generated-artifacts/MultiSigWallet.json",
"./generated-artifacts/MultiSigWalletWithTimeLock.json",
"./generated-artifacts/OrderValidator.json",