* WIP add combinatorial tests for internal Exchange functions * Change combinitorial testing strategy based on feedback * Check value of filled[orderHash] in updateFilledState tests * Add combinatorial tests for addFillResults * Add combinatorial tests for getPartialAmount * Implement generic `testWithReferenceFuncAsync` * Implement generic `testCombinatoriallyWithReferenceFuncAsync` * Add combinatorial tests for isRoundingError * Add combinatorial tests for calculateFillResults * Add support for Geth in internal contract tests * Fix contract artifacts * Change DECIMAL_PLACES to 78 and add a note. * Document new functions in utils * Optimize tests by only reseting state when needed * Rename/move some files * Print parameter names on failure in testWithReferenceFuncAsync * Add to changelog for utils package * Appease various linters * Rename some more things related to FillOrderCombinatorialUtils * Remove .only from test/exchange/internal.ts * Remove old test for isRoundingError and getPartialAmount * Appease linters again * Remove old todos * Fix typos, add comments, rename some things * Re-add some LibMath tests * Update contract internal tests to use new SafeMath revert reasons * Apply PR feedback from Amir * Apply PR feedback from Remco * Re-add networks to ZRXToken artifact * Remove duplicate Whitelist in compiler.json
126 lines
5.8 KiB
TypeScript
126 lines
5.8 KiB
TypeScript
import { BlockchainLifecycle } from '@0xproject/dev-utils';
|
|
import { assetDataUtils, EIP712Utils, orderHashUtils } from '@0xproject/order-utils';
|
|
import { SignedOrder } from '@0xproject/types';
|
|
import { BigNumber } from '@0xproject/utils';
|
|
import * as chai from 'chai';
|
|
|
|
import { TestConstantsContract } from '../../generated_contract_wrappers/test_constants';
|
|
import { TestLibsContract } from '../../generated_contract_wrappers/test_libs';
|
|
import { addressUtils } from '../utils/address_utils';
|
|
import { artifacts } from '../utils/artifacts';
|
|
import { chaiSetup } from '../utils/chai_setup';
|
|
import { constants } from '../utils/constants';
|
|
import { OrderFactory } from '../utils/order_factory';
|
|
import { provider, txDefaults, web3Wrapper } from '../utils/web3_wrapper';
|
|
|
|
chaiSetup.configure();
|
|
const expect = chai.expect;
|
|
|
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
|
|
|
describe('Exchange libs', () => {
|
|
let signedOrder: SignedOrder;
|
|
let orderFactory: OrderFactory;
|
|
let libs: TestLibsContract;
|
|
let testConstants: TestConstantsContract;
|
|
|
|
before(async () => {
|
|
await blockchainLifecycle.startAsync();
|
|
});
|
|
after(async () => {
|
|
await blockchainLifecycle.revertAsync();
|
|
});
|
|
before(async () => {
|
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
|
const makerAddress = accounts[0];
|
|
libs = await TestLibsContract.deployFrom0xArtifactAsync(artifacts.TestLibs, provider, txDefaults);
|
|
testConstants = await TestConstantsContract.deployFrom0xArtifactAsync(
|
|
artifacts.TestConstants,
|
|
provider,
|
|
txDefaults,
|
|
);
|
|
|
|
const defaultOrderParams = {
|
|
...constants.STATIC_ORDER_PARAMS,
|
|
exchangeAddress: libs.address,
|
|
makerAddress,
|
|
feeRecipientAddress: addressUtils.generatePseudoRandomAddress(),
|
|
makerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
|
|
takerAssetData: assetDataUtils.encodeERC20AssetData(addressUtils.generatePseudoRandomAddress()),
|
|
};
|
|
const privateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(makerAddress)];
|
|
orderFactory = new OrderFactory(privateKey, defaultOrderParams);
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
await blockchainLifecycle.startAsync();
|
|
});
|
|
afterEach(async () => {
|
|
await blockchainLifecycle.revertAsync();
|
|
});
|
|
|
|
describe('LibConstants', () => {
|
|
describe('ZRX_ASSET_DATA', () => {
|
|
it('should have the correct ZRX_ASSET_DATA', async () => {
|
|
const isValid = await testConstants.assertValidZrxAssetData.callAsync();
|
|
expect(isValid).to.be.equal(true);
|
|
});
|
|
});
|
|
});
|
|
// Note(albrow): These tests are designed to be supplemental to the
|
|
// combinatorial tests in test/exchange/internal. They test specific edge
|
|
// cases that are not covered by the combinatorial tests.
|
|
describe('LibMath', () => {
|
|
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 libs.publicIsRoundingError.callAsync(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 libs.publicIsRoundingError.callAsync(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 libs.publicIsRoundingError.callAsync(numerator, denominator, target);
|
|
expect(isRoundingError).to.be.true();
|
|
});
|
|
});
|
|
|
|
describe('LibOrder', () => {
|
|
describe('getOrderSchema', () => {
|
|
it('should output the correct order schema hash', async () => {
|
|
const orderSchema = await libs.getOrderSchemaHash.callAsync();
|
|
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();
|
|
const domainSchemaBuffer = EIP712Utils._getDomainSeparatorSchemaBuffer();
|
|
const schemaHashHex = `0x${domainSchemaBuffer.toString('hex')}`;
|
|
expect(schemaHashHex).to.be.equal(domainSeparatorSchema);
|
|
});
|
|
});
|
|
describe('getOrderHash', () => {
|
|
it('should output the correct orderHash', async () => {
|
|
signedOrder = await orderFactory.newSignedOrderAsync();
|
|
const orderHashHex = await libs.publicGetOrderHash.callAsync(signedOrder);
|
|
expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(orderHashHex);
|
|
});
|
|
});
|
|
});
|
|
});
|