Xianny fcbcbac889
Remove assetDataUtils everywhere (#2373)
* remove assetDataUtils everywhere

* export IAssetDataContract from @0x/contract-wrappers to allow @0x/instant to decode asset data  synchronously

* export generic function `decodeAssetDataOrThrow` and add ERC20Bridge support

* export `hexUtils` from order-utils instead of contracts-test-utils
2019-12-04 13:08:08 -08:00

183 lines
8.0 KiB
TypeScript

import { IAssetDataContract } from '@0x/contracts-asset-proxy';
import {
artifacts as ERC20Artifacts,
DummyERC20TokenContract,
ERC20TokenEvents,
ERC20TokenTransferEventArgs,
} from '@0x/contracts-erc20';
import {
artifacts as ERC721Artifacts,
DummyERC721TokenContract,
ERC721TokenEvents,
ERC721TokenTransferEventArgs,
} from '@0x/contracts-erc721';
import {
blockchainTests,
constants,
expect,
getRandomInteger,
randomAddress,
verifyEventsFromLogs,
} from '@0x/contracts-test-utils';
import { BigNumber, ExchangeForwarderRevertErrors, hexUtils } from '@0x/utils';
import { artifacts } from './artifacts';
import { TestForwarderContract } from './wrappers';
blockchainTests('Supported asset type unit tests', env => {
let forwarder: TestForwarderContract;
let assetDataEncoder: IAssetDataContract;
let bridgeAddress: string;
let bridgeData: string;
let receiver: string;
let erc20Token: DummyERC20TokenContract;
let erc721Token: DummyERC721TokenContract;
let nftId: BigNumber;
let erc20AssetData: string;
let erc721AssetData: string;
let erc20BridgeAssetData: string;
before(async () => {
[receiver] = await env.getAccountAddressesAsync();
assetDataEncoder = new IAssetDataContract(constants.NULL_ADDRESS, env.provider);
forwarder = await TestForwarderContract.deployFrom0xArtifactAsync(
artifacts.TestForwarder,
env.provider,
env.txDefaults,
{ ...artifacts, ...ERC20Artifacts, ...ERC721Artifacts },
);
erc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
ERC20Artifacts.DummyERC20Token,
env.provider,
env.txDefaults,
ERC20Artifacts,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
constants.DUMMY_TOKEN_DECIMALS,
constants.DUMMY_TOKEN_TOTAL_SUPPLY,
);
erc20AssetData = assetDataEncoder.ERC20Token(erc20Token.address).getABIEncodedTransactionData();
erc721Token = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
ERC721Artifacts.DummyERC721Token,
env.provider,
env.txDefaults,
ERC721Artifacts,
constants.DUMMY_TOKEN_NAME,
constants.DUMMY_TOKEN_SYMBOL,
);
nftId = getRandomInteger(constants.ZERO_AMOUNT, constants.MAX_UINT256);
erc721AssetData = assetDataEncoder.ERC721Token(erc721Token.address, nftId).getABIEncodedTransactionData();
bridgeAddress = randomAddress();
bridgeData = hexUtils.random();
erc20BridgeAssetData = assetDataEncoder
.ERC20Bridge(erc20Token.address, bridgeAddress, bridgeData)
.getABIEncodedTransactionData();
});
describe('_areUnderlyingAssetsEqual', () => {
it('returns true if assetData1 == assetData2 are ERC20', async () => {
const result = await forwarder.areUnderlyingAssetsEqual(erc20AssetData, erc20AssetData).callAsync();
expect(result).to.be.true();
});
it('returns true if assetData1 == assetData2 are ERC20Bridge', async () => {
const result = await forwarder
.areUnderlyingAssetsEqual(erc20BridgeAssetData, erc20BridgeAssetData)
.callAsync();
expect(result).to.be.true();
});
it('returns true if assetData2 is the ERC20Bridge equivalent of assetData1', async () => {
const result = await forwarder.areUnderlyingAssetsEqual(erc20AssetData, erc20BridgeAssetData).callAsync();
expect(result).to.be.true();
});
it('returns false if assetData1 != assetData2 are ERC20', async () => {
const differentERC20AssetData = assetDataEncoder.ERC20Token(randomAddress()).getABIEncodedTransactionData();
const result = await forwarder
.areUnderlyingAssetsEqual(erc20AssetData, differentERC20AssetData)
.callAsync();
expect(result).to.be.false();
});
it('returns false if assetData1 is ERC20 and assetData2 is ERC721', async () => {
const result = await forwarder.areUnderlyingAssetsEqual(erc20AssetData, erc721AssetData).callAsync();
expect(result).to.be.false();
});
it('returns false if assetData2 is ERC20Bridge, but for a different token than assetData1', async () => {
const mismatchedErc20BridgeAssetData = assetDataEncoder
.ERC20Bridge(randomAddress(), bridgeAddress, bridgeData)
.getABIEncodedTransactionData();
const result = await forwarder
.areUnderlyingAssetsEqual(erc20AssetData, mismatchedErc20BridgeAssetData)
.callAsync();
expect(result).to.be.false();
});
it('returns false if assetData1 == assetData2 are ERC721', async () => {
const result = await forwarder.areUnderlyingAssetsEqual(erc721AssetData, erc721AssetData).callAsync();
expect(result).to.be.false();
});
});
describe('_transferAssetToSender', () => {
const TRANSFER_AMOUNT = new BigNumber(1);
before(async () => {
await erc20Token
.setBalance(forwarder.address, constants.INITIAL_ERC20_BALANCE)
.awaitTransactionSuccessAsync();
await erc721Token.mint(forwarder.address, nftId).awaitTransactionSuccessAsync();
});
it('transfers an ERC20 token given ERC20 assetData', async () => {
const txReceipt = await forwarder
.transferAssetToSender(erc20AssetData, TRANSFER_AMOUNT)
.awaitTransactionSuccessAsync({ from: receiver });
verifyEventsFromLogs<ERC20TokenTransferEventArgs>(
txReceipt.logs,
[{ _from: forwarder.address, _to: receiver, _value: TRANSFER_AMOUNT }],
ERC20TokenEvents.Transfer,
);
});
it('transfers an ERC721 token given ERC721 assetData and amount == 1', async () => {
const txReceipt = await forwarder
.transferAssetToSender(erc721AssetData, TRANSFER_AMOUNT)
.awaitTransactionSuccessAsync({ from: receiver });
verifyEventsFromLogs<ERC721TokenTransferEventArgs>(
txReceipt.logs,
[{ _from: forwarder.address, _to: receiver, _tokenId: nftId }],
ERC721TokenEvents.Transfer,
);
});
it('reverts if attempting to transfer an ERC721 token with amount != 1', async () => {
const invalidAmount = new BigNumber(2);
const tx = forwarder
.transferAssetToSender(erc721AssetData, invalidAmount)
.awaitTransactionSuccessAsync({ from: receiver });
const expectedError = new ExchangeForwarderRevertErrors.Erc721AmountMustEqualOneError(invalidAmount);
return expect(tx).to.revertWith(expectedError);
});
it('transfers an ERC20 token given ERC20Bridge assetData', async () => {
const txReceipt = await forwarder
.transferAssetToSender(erc20BridgeAssetData, TRANSFER_AMOUNT)
.awaitTransactionSuccessAsync({ from: receiver });
verifyEventsFromLogs<ERC20TokenTransferEventArgs>(
txReceipt.logs,
[{ _from: forwarder.address, _to: receiver, _value: TRANSFER_AMOUNT }],
ERC20TokenEvents.Transfer,
);
});
it('reverts if assetData is unsupported', async () => {
const randomBytes = hexUtils.random();
const tx = forwarder
.transferAssetToSender(randomBytes, TRANSFER_AMOUNT)
.awaitTransactionSuccessAsync({ from: receiver });
const expectedError = new ExchangeForwarderRevertErrors.UnsupportedAssetProxyError(
hexUtils.slice(randomBytes, 0, 4),
);
return expect(tx).to.revertWith(expectedError);
});
});
});