Merge branch 'v2-prototype' into feature/combinatorial-testing

* v2-prototype: (22 commits)
  Fix closing parens in liborder
  Update after rebase
  ERC721Proxy Always call safeTransferFrom
  Rename makerEpoch => orderEpoch
  Make cancelOrdersUpTo compatible with sender abstraction
  Update PR template
  Use Image component instead of img tag
  Assembler orderHash function
  Optimize and remove redundant encodePacked
  Fix linting issue
  Fix bug where we do fetch balances on wallet login
  Check network state immediately instead of waiting for delay
  Fix onboarding persisting when changing routes
  Consolidate account state messaging logic
  Only elevate wallet zIndex when onboarding is in progress
  Rebase and update feedback
  Run linter
  Add Portal v2 logging
  Simplified handling of source < 32 edge case
  Basic EIP712 encoder
  ...
This commit is contained in:
Fabio Berger
2018-06-20 13:25:29 +02:00
48 changed files with 1167 additions and 366 deletions

View File

@@ -279,7 +279,7 @@ describe('Asset Transfer Proxies', () => {
expect(newOwnerMakerAsset).to.be.bignumber.equal(takerAddress);
});
it('should not call onERC721Received when transferring to a smart contract without receiver data', async () => {
it('should call onERC721Received when transferring to a smart contract without receiver data', async () => {
// Construct ERC721 asset data
const encodedAssetData = assetProxyUtils.encodeERC721AssetData(erc721Token.address, erc721MakerTokenId);
const encodedAssetDataWithoutProxyId = encodedAssetData.slice(0, -2);
@@ -300,7 +300,11 @@ describe('Asset Transfer Proxies', () => {
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);
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(constants.NULL_BYTES);
// Verify transfer was successful
const newOwnerMakerAsset = await erc721Token.ownerOf.callAsync(erc721MakerTokenId);
expect(newOwnerMakerAsset).to.be.bignumber.equal(erc721Receiver.address);

View File

@@ -252,30 +252,30 @@ describe('Exchange core', () => {
});
describe('cancelOrdersUpTo', () => {
it('should fail to set makerEpoch less than current makerEpoch', async () => {
const makerEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress);
const lesserMakerEpoch = new BigNumber(0);
it('should fail to set orderEpoch less than current orderEpoch', async () => {
const orderEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress);
const lesserOrderEpoch = new BigNumber(0);
return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrdersUpToAsync(lesserMakerEpoch, makerAddress),
exchangeWrapper.cancelOrdersUpToAsync(lesserOrderEpoch, makerAddress),
);
});
it('should fail to set makerEpoch equal to existing makerEpoch', async () => {
const makerEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress);
it('should fail to set orderEpoch equal to existing orderEpoch', async () => {
const orderEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress);
return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress),
exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress),
);
});
it('should cancel only orders with a makerEpoch less than existing makerEpoch', async () => {
// Cancel all transactions with a makerEpoch less than 1
const makerEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(makerEpoch, makerAddress);
it('should cancel only orders with a orderEpoch less than existing orderEpoch', async () => {
// Cancel all transactions with a orderEpoch less than 1
const orderEpoch = new BigNumber(1);
await exchangeWrapper.cancelOrdersUpToAsync(orderEpoch, makerAddress);
// Create 3 orders with makerEpoch values: 0,1,2,3
// Since we cancelled with makerEpoch=1, orders with makerEpoch<=1 will not be processed
// Create 3 orders with orderEpoch values: 0,1,2,3
// Since we cancelled with orderEpoch=1, orders with orderEpoch<=1 will not be processed
erc20Balances = await erc20Wrapper.getBalancesAsync();
const signedOrders = [
orderFactory.newSignedOrder({

View File

@@ -1,5 +1,5 @@
import { BlockchainLifecycle } from '@0xproject/dev-utils';
import { assetProxyUtils, orderHashUtils } from '@0xproject/order-utils';
import { assetProxyUtils, EIP712Utils, orderHashUtils } from '@0xproject/order-utils';
import { SignedOrder } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as chai from 'chai';
@@ -56,13 +56,17 @@ describe('Exchange libs', () => {
describe('getOrderSchema', () => {
it('should output the correct order schema hash', async () => {
const orderSchema = await libs.getOrderSchemaHash.callAsync();
expect(orderHashUtils._getOrderSchemaHex()).to.be.equal(orderSchema);
const schemaHashBuffer = orderHashUtils._getOrderSchemaBuffer();
const schemaHashHex = `0x${schemaHashBuffer.toString('hex')}`;
expect(schemaHashHex).to.be.equal(orderSchema);
});
});
describe('getDomainSeparatorSchema', () => {
it('should output the correct domain separator schema hash', async () => {
const domainSeparatorSchema = await libs.getDomainSeparatorSchemaHash.callAsync();
expect(orderHashUtils._getDomainSeparatorSchemaHex()).to.be.equal(domainSeparatorSchema);
const domainSchemaBuffer = EIP712Utils._getDomainSeparatorSchemaBuffer();
const schemaHashHex = `0x${domainSchemaBuffer.toString('hex')}`;
expect(schemaHashHex).to.be.equal(domainSeparatorSchema);
});
});
describe('getOrderHash', () => {

View File

@@ -7,6 +7,7 @@ import * as chai from 'chai';
import { DummyERC20TokenContract } from '../../src/generated_contract_wrappers/dummy_e_r_c20_token';
import { ERC20ProxyContract } from '../../src/generated_contract_wrappers/e_r_c20_proxy';
import { ExchangeContract } from '../../src/generated_contract_wrappers/exchange';
import { ExchangeWrapperContract } from '../../src/generated_contract_wrappers/exchange_wrapper';
import { WhitelistContract } from '../../src/generated_contract_wrappers/whitelist';
import { artifacts } from '../../src/utils/artifacts';
import { expectRevertOrAlwaysFailingTransactionAsync } from '../../src/utils/assertions';
@@ -201,6 +202,117 @@ describe('Exchange transactions', () => {
);
});
});
describe('cancelOrdersUpTo', () => {
let exchangeWrapperContract: ExchangeWrapperContract;
before(async () => {
exchangeWrapperContract = await ExchangeWrapperContract.deployFrom0xArtifactAsync(
artifacts.ExchangeWrapper,
provider,
txDefaults,
exchange.address,
);
});
it("should cancel an order if called from the order's sender", async () => {
const orderSalt = new BigNumber(0);
signedOrder = orderFactory.newSignedOrder({
senderAddress: exchangeWrapperContract.address,
salt: orderSalt,
});
const targetOrderEpoch = orderSalt.add(1);
const cancelData = exchange.cancelOrdersUpTo.getABIEncodedTransactionData(targetOrderEpoch);
const signedCancelTx = makerTransactionFactory.newSignedTransaction(cancelData);
await exchangeWrapperContract.cancelOrdersUpTo.sendTransactionAsync(
targetOrderEpoch,
signedCancelTx.salt,
signedCancelTx.signature,
{
from: makerAddress,
},
);
const takerAssetFillAmount = signedOrder.takerAssetAmount;
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const fillData = exchange.fillOrder.getABIEncodedTransactionData(
orderWithoutExchangeAddress,
takerAssetFillAmount,
signedOrder.signature,
);
const signedFillTx = takerTransactionFactory.newSignedTransaction(fillData);
return expectRevertOrAlwaysFailingTransactionAsync(
exchangeWrapperContract.fillOrder.sendTransactionAsync(
orderWithoutExchangeAddress,
takerAssetFillAmount,
signedFillTx.salt,
signedOrder.signature,
signedFillTx.signature,
{ from: takerAddress },
),
);
});
it("should not cancel an order if not called from the order's sender", async () => {
const orderSalt = new BigNumber(0);
signedOrder = orderFactory.newSignedOrder({
senderAddress: exchangeWrapperContract.address,
salt: orderSalt,
});
const targetOrderEpoch = orderSalt.add(1);
await exchangeWrapper.cancelOrdersUpToAsync(targetOrderEpoch, makerAddress);
erc20Balances = await erc20Wrapper.getBalancesAsync();
const takerAssetFillAmount = signedOrder.takerAssetAmount;
orderWithoutExchangeAddress = orderUtils.getOrderWithoutExchangeAddress(signedOrder);
const data = exchange.fillOrder.getABIEncodedTransactionData(
orderWithoutExchangeAddress,
takerAssetFillAmount,
signedOrder.signature,
);
signedTx = takerTransactionFactory.newSignedTransaction(data);
await exchangeWrapperContract.fillOrder.sendTransactionAsync(
orderWithoutExchangeAddress,
takerAssetFillAmount,
signedTx.salt,
signedOrder.signature,
signedTx.signature,
{ from: takerAddress },
);
const newBalances = await erc20Wrapper.getBalancesAsync();
const makerAssetFillAmount = takerAssetFillAmount
.times(signedOrder.makerAssetAmount)
.dividedToIntegerBy(signedOrder.takerAssetAmount);
const makerFeePaid = signedOrder.makerFee
.times(makerAssetFillAmount)
.dividedToIntegerBy(signedOrder.makerAssetAmount);
const takerFeePaid = signedOrder.takerFee
.times(makerAssetFillAmount)
.dividedToIntegerBy(signedOrder.makerAssetAmount);
expect(newBalances[makerAddress][defaultMakerTokenAddress]).to.be.bignumber.equal(
erc20Balances[makerAddress][defaultMakerTokenAddress].minus(makerAssetFillAmount),
);
expect(newBalances[makerAddress][defaultTakerTokenAddress]).to.be.bignumber.equal(
erc20Balances[makerAddress][defaultTakerTokenAddress].add(takerAssetFillAmount),
);
expect(newBalances[makerAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[makerAddress][zrxToken.address].minus(makerFeePaid),
);
expect(newBalances[takerAddress][defaultTakerTokenAddress]).to.be.bignumber.equal(
erc20Balances[takerAddress][defaultTakerTokenAddress].minus(takerAssetFillAmount),
);
expect(newBalances[takerAddress][defaultMakerTokenAddress]).to.be.bignumber.equal(
erc20Balances[takerAddress][defaultMakerTokenAddress].add(makerAssetFillAmount),
);
expect(newBalances[takerAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[takerAddress][zrxToken.address].minus(takerFeePaid),
);
expect(newBalances[feeRecipientAddress][zrxToken.address]).to.be.bignumber.equal(
erc20Balances[feeRecipientAddress][zrxToken.address].add(makerFeePaid.add(takerFeePaid)),
);
});
});
});
describe('Whitelist', () => {