aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/test/asset_proxy/proxies.ts
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-06-12 06:23:48 +0800
committerFabio Berger <me@fabioberger.com>2018-06-12 06:23:48 +0800
commit7e78f5941ad9cb2fd5225899f79823c7376894c0 (patch)
tree13fadf90f821e9fead1373a2e567e6d86fe27e0f /packages/contracts/test/asset_proxy/proxies.ts
parent20f93185975d16c77492f05eb86dd89695539cd9 (diff)
parentbc0ae6be318a15bf8670a6da9a59d9bdb12cadae (diff)
downloaddexon-0x-contracts-7e78f5941ad9cb2fd5225899f79823c7376894c0.tar.gz
dexon-0x-contracts-7e78f5941ad9cb2fd5225899f79823c7376894c0.tar.zst
dexon-0x-contracts-7e78f5941ad9cb2fd5225899f79823c7376894c0.zip
Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (68 commits) Stop exporting ArtifactWriter Fix no-unused-variable tslint rule to include parameters and fix issues Fix linter exclude rule Validate all signature types rather then only ECSignatures Store the instantiated OrderValidationUtils Remove global hooks from tests and deploy contracts from within the specific tests Add EmitStatement to ASTVisitor Fix tslint issues Add back artifacts file Fix a bug in SolCompilerArtifacts adapter config overriding Move OrderValidationUtils (+ tests) and ExchangeTransferSimulator to order-utils export parseECSignature method Export ArtifactWriter from migrations package Remove unused artifact file Pass in generated contract wrapper to orderValidationUtils at instantiation Refactor orderValidationUtils to use the generated contract wrapper instead of the higher-level one Refactor ExchangeTransferSimulator public interface to accet an AbstractBalanceAndProxyAllowanceLazyStore so that this module could be re-used in different contexts. Increase timeout for contract migrations Remove some copy-paste code Await transactions in migrations ...
Diffstat (limited to 'packages/contracts/test/asset_proxy/proxies.ts')
-rw-r--r--packages/contracts/test/asset_proxy/proxies.ts234
1 files changed, 150 insertions, 84 deletions
diff --git a/packages/contracts/test/asset_proxy/proxies.ts b/packages/contracts/test/asset_proxy/proxies.ts
index d14280c5f..08376ccfb 100644
--- a/packages/contracts/test/asset_proxy/proxies.ts
+++ b/packages/contracts/test/asset_proxy/proxies.ts
@@ -1,24 +1,33 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
-import { assetProxyUtils } from '@0xproject/order-utils';
+import { assetProxyUtils, generatePseudoRandomSalt } from '@0xproject/order-utils';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
+import { LogWithDecodedArgs } from 'ethereum-types';
+import ethUtil = require('ethereumjs-util');
import * as _ from 'lodash';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token';
+import {
+ DummyERC721ReceiverContract,
+ TokenReceivedContractEventArgs,
+} from '../../src/generated_contract_wrappers/dummy_e_r_c721_receiver';
import { DummyERC721TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c721_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy';
import { ERC721ProxyContract } from '../../src/generated_contract_wrappers/e_r_c721_proxy';
+import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
import { chaiSetup } from '../../src/utils/chai_setup';
import { constants } from '../../src/utils/constants';
import { ERC20Wrapper } from '../../src/utils/erc20_wrapper';
import { ERC721Wrapper } from '../../src/utils/erc721_wrapper';
-import { provider, web3Wrapper } from '../../src/utils/web3_wrapper';
+import { LogDecoder } from '../../src/utils/log_decoder';
+import { provider, txDefaults, web3Wrapper } from '../../src/utils/web3_wrapper';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
+// tslint:disable:no-unnecessary-type-assertion
describe('Asset Transfer Proxies', () => {
let owner: string;
let notAuthorized: string;
@@ -28,6 +37,7 @@ describe('Asset Transfer Proxies', () => {
let zrxToken: DummyERC20TokenContract;
let erc721Token: DummyERC721TokenContract;
+ let erc721Receiver: DummyERC721ReceiverContract;
let erc20Proxy: ERC20ProxyContract;
let erc721Proxy: ERC721ProxyContract;
@@ -69,6 +79,11 @@ describe('Asset Transfer Proxies', () => {
}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
+ erc721Receiver = await DummyERC721ReceiverContract.deployFrom0xArtifactAsync(
+ artifacts.DummyERC721Receiver,
+ provider,
+ txDefaults,
+ );
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -79,14 +94,14 @@ describe('Asset Transfer Proxies', () => {
describe('Transfer Proxy - ERC20', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
- // Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ // Construct ERC20 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -105,14 +120,14 @@ describe('Asset Transfer Proxies', () => {
});
it('should do nothing if transferring 0 amount of a token', async () => {
- // Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ // Construct ERC20 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -131,8 +146,8 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if allowances are too low', async () => {
- // Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ // Construct ERC20 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0);
const transferAmount = new BigNumber(10);
@@ -145,7 +160,7 @@ describe('Asset Transfer Proxies', () => {
// Perform a transfer; expect this to fail.
return expectRevertOrAlwaysFailingTransactionAsync(
erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
transferAmount,
@@ -155,20 +170,14 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if requesting address is not authorized', async () => {
- // Construct metadata for ERC20 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ // Construct ERC20 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10);
return expectRevertOrAlwaysFailingTransactionAsync(
- erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
- makerAddress,
- takerAddress,
- amount,
- {
- from: notAuthorized,
- },
- ),
+ erc20Proxy.transferFrom.sendTransactionAsync(encodedAssetData, makerAddress, takerAddress, amount, {
+ from: notAuthorized,
+ }),
);
});
});
@@ -177,16 +186,16 @@ describe('Asset Transfer Proxies', () => {
it('should succesfully make multiple token transfers', async () => {
const erc20Balances = await erc20Wrapper.getBalancesAsync();
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const amount = new BigNumber(10);
const numTransfers = 2;
- const assetMetadata = _.times(numTransfers, () => encodedProxyMetadata);
+ const assetData = _.times(numTransfers, () => encodedAssetData);
const fromAddresses = _.times(numTransfers, () => makerAddress);
const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => amount);
const txHash = await erc20Proxy.batchTransferFrom.sendTransactionAsync(
- assetMetadata,
+ assetData,
fromAddresses,
toAddresses,
amounts,
@@ -208,22 +217,18 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if not called by an authorized address', async () => {
- const encodedProxyMetadata = assetProxyUtils.encodeERC20ProxyData(zrxToken.address);
+ const encodedAssetData = assetProxyUtils.encodeERC20AssetData(zrxToken.address);
const amount = new BigNumber(10);
const numTransfers = 2;
- const assetMetadata = _.times(numTransfers, () => encodedProxyMetadata);
+ const assetData = _.times(numTransfers, () => encodedAssetData);
const fromAddresses = _.times(numTransfers, () => makerAddress);
const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => amount);
return expectRevertOrAlwaysFailingTransactionAsync(
- erc20Proxy.batchTransferFrom.sendTransactionAsync(
- assetMetadata,
- fromAddresses,
- toAddresses,
- amounts,
- { from: notAuthorized },
- ),
+ erc20Proxy.batchTransferFrom.sendTransactionAsync(assetData, fromAddresses, toAddresses, amounts, {
+ from: notAuthorized,
+ }),
);
});
});
@@ -237,11 +242,8 @@ describe('Asset Transfer Proxies', () => {
describe('Transfer Proxy - ERC721', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
- erc721Token.address,
- erc721MakerTokenId,
- );
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -249,7 +251,7 @@ describe('Asset Transfer Proxies', () => {
const amount = new BigNumber(1);
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -262,12 +264,94 @@ describe('Asset Transfer Proxies', () => {
expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress);
});
- it('should throw if transferring 0 amount of a token', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
+ it('should not call onERC721Received when transferring to a smart contract without receiver data', async () => {
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
+ // Verify pre-condition
+ const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
+ // Perform a transfer from makerAddress to takerAddress
+ const amount = new BigNumber(1);
+ const txHash = await erc721Proxy.transferFrom.sendTransactionAsync(
+ encodedAssetData,
+ makerAddress,
+ erc721Receiver.address,
+ amount,
+ { from: exchangeAddress },
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
+ // Parse transaction logs
+ const logDecoder = new LogDecoder(web3Wrapper, erc721Receiver.address);
+ const tx = await logDecoder.getTxWithDecodedLogsAsync(txHash);
+ // Verify that no log was emitted by erc721 receiver
+ expect(tx.logs.length).to.be.equal(0);
+ // Verify transfer was successful
+ const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address);
+ });
+
+ it('should call onERC721Received when transferring to a smart contract with receiver data', async () => {
+ // Construct ERC721 asset data
+ const receiverData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt()));
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(
+ erc721Token.address,
+ erc721MakerTokenId,
+ receiverData,
+ );
+ // Verify pre-condition
+ const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
+ // Perform a transfer from makerAddress to takerAddress
+ const amount = new BigNumber(1);
+ const txHash = await erc721Proxy.transferFrom.sendTransactionAsync(
+ encodedAssetData,
+ makerAddress,
+ erc721Receiver.address,
+ amount,
+ { from: exchangeAddress },
+ );
+ await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS);
+ // Parse transaction logs
+ const logDecoder = new LogDecoder(web3Wrapper, erc721Receiver.address);
+ const tx = await logDecoder.getTxWithDecodedLogsAsync(txHash);
+ // Validate log emitted by erc721 receiver
+ expect(tx.logs.length).to.be.equal(1);
+ const tokenReceivedLog = tx.logs[0] as LogWithDecodedArgs<TokenReceivedContractEventArgs>;
+ expect(tokenReceivedLog.args.from).to.be.equal(makerAddress);
+ expect(tokenReceivedLog.args.tokenId).to.be.bignumber.equal(erc721MakerTokenId);
+ expect(tokenReceivedLog.args.data).to.be.equal(receiverData);
+ // Verify transfer was successful
+ const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address);
+ });
+
+ it('should throw if there is receiver data but contract does not have onERC721Received', async () => {
+ // Construct ERC721 asset data
+ const receiverData = ethUtil.bufferToHex(assetProxyUtils.encodeUint256(generatePseudoRandomSalt()));
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(
erc721Token.address,
erc721MakerTokenId,
+ receiverData,
+ );
+ // Verify pre-condition
+ const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
+ expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
+ // Perform a transfer from makerAddress to takerAddress
+ const amount = new BigNumber(1);
+ return expectRevertOrAlwaysFailingTransactionAsync(
+ erc721Proxy.transferFrom.sendTransactionAsync(
+ encodedAssetData,
+ makerAddress,
+ erc20Proxy.address, // the ERC20 proxy does not have an ERC721 receiver
+ amount,
+ { from: exchangeAddress },
+ ),
);
+ });
+
+ it('should throw if transferring 0 amount of a token', async () => {
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -275,7 +359,7 @@ describe('Asset Transfer Proxies', () => {
const amount = new BigNumber(0);
return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -285,11 +369,8 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if transferring > 1 amount of a token', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
- erc721Token.address,
- erc721MakerTokenId,
- );
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Verify pre-condition
const ownerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(ownerMakerAsset).to.be.bignumber.equal(makerAddress);
@@ -297,7 +378,7 @@ describe('Asset Transfer Proxies', () => {
const amount = new BigNumber(500);
return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -307,11 +388,8 @@ describe('Asset Transfer Proxies', () => {
});
it('should throw if allowances are too low', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
- erc721Token.address,
- erc721MakerTokenId,
- );
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Remove transfer approval for makerAddress.
await web3Wrapper.awaitTransactionSuccessAsync(
await erc721Token.setApprovalForAll.sendTransactionAsync(erc721Proxy.address, false, {
@@ -322,29 +400,20 @@ describe('Asset Transfer Proxies', () => {
// Perform a transfer; expect this to fail.
const amount = new BigNumber(1);
return expectRevertOrAlwaysFailingTransactionAsync(
- erc20Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
- makerAddress,
- takerAddress,
- amount,
- {
- from: notAuthorized,
- },
- ),
+ erc20Proxy.transferFrom.sendTransactionAsync(encodedAssetData, makerAddress, takerAddress, amount, {
+ from: notAuthorized,
+ }),
);
});
it('should throw if requesting address is not authorized', async () => {
- // Construct metadata for ERC721 proxy
- const encodedProxyMetadata = assetProxyUtils.encodeERC721ProxyData(
- erc721Token.address,
- erc721MakerTokenId,
- );
+ // Construct ERC721 asset data
+ const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(1);
return expectRevertOrAlwaysFailingTransactionAsync(
erc721Proxy.transferFrom.sendTransactionAsync(
- encodedProxyMetadata,
+ encodedAssetData,
makerAddress,
takerAddress,
amount,
@@ -360,16 +429,16 @@ describe('Asset Transfer Proxies', () => {
const [makerTokenIdA, makerTokenIdB] = erc721TokensById[makerAddress][erc721Token.address];
const numTransfers = 2;
- const assetMetadata = [
- assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdA),
- assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdB),
+ const assetData = [
+ assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdA),
+ assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdB),
];
const fromAddresses = _.times(numTransfers, () => makerAddress);
const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => new BigNumber(1));
const txHash = await erc721Proxy.batchTransferFrom.sendTransactionAsync(
- assetMetadata,
+ assetData,
fromAddresses,
toAddresses,
amounts,
@@ -392,22 +461,18 @@ describe('Asset Transfer Proxies', () => {
const [makerTokenIdA, makerTokenIdB] = erc721TokensById[makerAddress][erc721Token.address];
const numTransfers = 2;
- const assetMetadata = [
- assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdA),
- assetProxyUtils.encodeERC721ProxyData(erc721Token.address, makerTokenIdB),
+ const assetData = [
+ assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdA),
+ assetProxyUtils.encodeERC721AssetData(erc721Token.address, makerTokenIdB),
];
const fromAddresses = _.times(numTransfers, () => makerAddress);
const toAddresses = _.times(numTransfers, () => takerAddress);
const amounts = _.times(numTransfers, () => new BigNumber(1));
return expectRevertOrAlwaysFailingTransactionAsync(
- erc721Proxy.batchTransferFrom.sendTransactionAsync(
- assetMetadata,
- fromAddresses,
- toAddresses,
- amounts,
- { from: notAuthorized },
- ),
+ erc721Proxy.batchTransferFrom.sendTransactionAsync(assetData, fromAddresses, toAddresses, amounts, {
+ from: notAuthorized,
+ }),
);
});
});
@@ -418,3 +483,4 @@ describe('Asset Transfer Proxies', () => {
});
});
});
+// tslint:enable:no-unnecessary-type-assertion