feat: mStable + FQT Rollup (#2662)
* feat: mStable * deploy and CHANGELOG * `@0x/contracts-utils`: Add more testnet addresses. * `@0x/contract-addresses`: Deply Mstable on testnets * `@0x/contract-addresses`: Remove testnet deployments of mStable :-) * move `erc20-bridge-sampler` into `asset-swapper` remove `DevUtils` dependency from sampler contract. * `@0x/asset-swapper`: Add ERC20BridgeSampler support for validating orders in maker fees denominated in non-maker assets. `@0x/asset-swapper`: Add tests for `NativeOrderSampler`. * `@0x/asset-swapper`: Return `0` sample if native order asset data is unsupported. * `@0x/asset-swapper`: Fix failing test. * feat: ExchangeProxy FQT fruit rollup (#2645) * feat: Optimize Bridges in ExchangeProxy * compile and most work * work around to trust the delecall contract * force allowances * Update Kyber/Eth2Dai bridges * Remove memory state where not required * cleanup * Combine Bridges into one adapter * mixins * refactor out ZeroExBridge * move out interface * comment out hacks * update migrations * remove simbot hacks * AdapterAddresses and mStable * Share constructor arg * fix migration * Remove whitespace * `@0x/contracts-zero-ex`: BridgeAdapter -- revert if bridge address is 0. * `@0x/contract-addresses`: Deploy FQT. Co-authored-by: Lawrence Forman <me@merklejerk.com> Co-authored-by: Lawrence Forman <lawrence@0xproject.com> * update ganache contract addresses * fix: asset-swapper empty batch call (#2669) * update ganache contract addresses * fix: asset-swapper prevent empty sampler batch call * add sampler to migrations * change migrations version * Use contract-wrappers and artifacts * remove extra data * remove deps, set sampler to NULL_ADDRESS * all the exports * noop sell rate too * update ganache contract addresses Co-authored-by: Lawrence Forman <me@merklejerk.com> Co-authored-by: Lawrence Forman <lawrence@0xproject.com>
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import { blockchainTests, describe, expect, toBaseUnitAmount, Web3ProviderEngine } from '@0x/contracts-test-utils';
|
||||
import { RPCSubprovider } from '@0x/subproviders';
|
||||
import { BigNumber, providerUtils } from '@0x/utils';
|
||||
|
||||
import { artifacts } from '../artifacts';
|
||||
import { ERC20BridgeSamplerContract } from '../wrappers';
|
||||
|
||||
export const VB = '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b';
|
||||
|
||||
// tslint:disable: custom-no-magic-numbers
|
||||
|
||||
blockchainTests.skip('Mainnet Sampler Tests', env => {
|
||||
let testContract: ERC20BridgeSamplerContract;
|
||||
const fakeSamplerAddress = '0x1111111111111111111111111111111111111111';
|
||||
const overrides = {
|
||||
[fakeSamplerAddress]: {
|
||||
code: artifacts.ERC20BridgeSampler.compilerOutput.evm.deployedBytecode.object,
|
||||
},
|
||||
};
|
||||
before(async () => {
|
||||
const provider = new Web3ProviderEngine();
|
||||
// tslint:disable-next-line:no-non-null-assertion
|
||||
provider.addProvider(new RPCSubprovider(process.env.RPC_URL!));
|
||||
providerUtils.startProviderEngine(provider);
|
||||
testContract = new ERC20BridgeSamplerContract(fakeSamplerAddress, provider, {
|
||||
...env.txDefaults,
|
||||
from: VB,
|
||||
});
|
||||
});
|
||||
describe('Curve', () => {
|
||||
const CURVE_ADDRESS = '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51';
|
||||
const DAI_TOKEN_INDEX = new BigNumber(0);
|
||||
const USDC_TOKEN_INDEX = new BigNumber(1);
|
||||
const CURVE_INFO = {
|
||||
poolAddress: CURVE_ADDRESS,
|
||||
sellQuoteFunctionSelector: '0x07211ef7',
|
||||
buyQuoteFunctionSelector: '0x0e71d1b9',
|
||||
};
|
||||
|
||||
describe('sampleSellsFromCurve()', () => {
|
||||
it('samples sells from Curve DAI->USDC', async () => {
|
||||
const samples = await testContract
|
||||
.sampleSellsFromCurve(CURVE_INFO, DAI_TOKEN_INDEX, USDC_TOKEN_INDEX, [toBaseUnitAmount(1)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
|
||||
it('samples sells from Curve USDC->DAI', async () => {
|
||||
const samples = await testContract
|
||||
.sampleSellsFromCurve(CURVE_INFO, USDC_TOKEN_INDEX, DAI_TOKEN_INDEX, [toBaseUnitAmount(1, 6)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sampleBuysFromCurve()', () => {
|
||||
it('samples buys from Curve DAI->USDC', async () => {
|
||||
// From DAI to USDC
|
||||
// I want to buy 1 USDC
|
||||
const samples = await testContract
|
||||
.sampleBuysFromCurve(CURVE_INFO, DAI_TOKEN_INDEX, USDC_TOKEN_INDEX, [toBaseUnitAmount(1, 6)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
|
||||
it('samples buys from Curve USDC->DAI', async () => {
|
||||
// From USDC to DAI
|
||||
// I want to buy 1 DAI
|
||||
const samples = await testContract
|
||||
.sampleBuysFromCurve(CURVE_INFO, USDC_TOKEN_INDEX, DAI_TOKEN_INDEX, [toBaseUnitAmount(1)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Kyber', () => {
|
||||
const WETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
|
||||
const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f';
|
||||
const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
|
||||
describe('sampleSellsFromKyberNetwork()', () => {
|
||||
it('samples sells from Kyber DAI->WETH', async () => {
|
||||
const samples = await testContract
|
||||
.sampleSellsFromKyberNetwork(DAI, WETH, [toBaseUnitAmount(1)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
it('samples sells from Kyber WETH->DAI', async () => {
|
||||
const samples = await testContract
|
||||
.sampleSellsFromKyberNetwork(WETH, DAI, [toBaseUnitAmount(1)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
it('samples sells from Kyber DAI->USDC', async () => {
|
||||
const samples = await testContract
|
||||
.sampleSellsFromKyberNetwork(DAI, USDC, [toBaseUnitAmount(1)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('sampleBuysFromKyber()', () => {
|
||||
it('samples buys from Kyber WETH->DAI', async () => {
|
||||
// From ETH to DAI
|
||||
// I want to buy 1 DAI
|
||||
const samples = await testContract
|
||||
.sampleBuysFromKyberNetwork(WETH, DAI, [toBaseUnitAmount(1)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
|
||||
it('samples buys from Kyber DAI->WETH', async () => {
|
||||
// From USDC to DAI
|
||||
// I want to buy 1 WETH
|
||||
const samples = await testContract
|
||||
.sampleBuysFromKyberNetwork(DAI, WETH, [toBaseUnitAmount(1)])
|
||||
.callAsync({ overrides });
|
||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
1036
packages/asset-swapper/test/contracts/erc20_bridge_sampler_test.ts
Normal file
1036
packages/asset-swapper/test/contracts/erc20_bridge_sampler_test.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,313 @@
|
||||
import {
|
||||
assertIntegerRoughlyEquals,
|
||||
blockchainTests,
|
||||
constants,
|
||||
expect,
|
||||
getRandomInteger,
|
||||
randomAddress,
|
||||
} from '@0x/contracts-test-utils';
|
||||
import { Order } from '@0x/types';
|
||||
import { BigNumber, hexUtils } from '@0x/utils';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { artifacts } from '../artifacts';
|
||||
import { TestNativeOrderSamplerContract } from '../wrappers';
|
||||
|
||||
const { NULL_BYTES, ZERO_AMOUNT } = constants;
|
||||
|
||||
// tslint:disable: custom-no-magic-numbers
|
||||
|
||||
blockchainTests.resets('NativeOrderSampler contract', env => {
|
||||
let testContract: TestNativeOrderSamplerContract;
|
||||
let makerToken: string;
|
||||
let takerToken: string;
|
||||
let feeToken: string;
|
||||
let erc20Proxy: string;
|
||||
const ERC20_PROXY_ID = '0xf47261b0';
|
||||
const VALID_SIGNATURE = '0x01';
|
||||
const INVALID_SIGNATURE = '0x00';
|
||||
|
||||
before(async () => {
|
||||
testContract = await TestNativeOrderSamplerContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestNativeOrderSampler,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
{},
|
||||
);
|
||||
erc20Proxy = await testContract.getAssetProxy(ERC20_PROXY_ID).callAsync();
|
||||
const NUM_TOKENS = new BigNumber(3);
|
||||
[makerToken, takerToken, feeToken] = await testContract.createTokens(NUM_TOKENS).callAsync();
|
||||
await testContract.createTokens(NUM_TOKENS).awaitTransactionSuccessAsync();
|
||||
});
|
||||
|
||||
function getPackedHash(...args: string[]): string {
|
||||
return hexUtils.hash(hexUtils.concat(...args.map(a => hexUtils.toHex(a))));
|
||||
}
|
||||
|
||||
interface OrderInfo {
|
||||
orderHash: string;
|
||||
orderStatus: number;
|
||||
orderTakerAssetFilledAmount: BigNumber;
|
||||
}
|
||||
|
||||
function getOrderInfo(order: Order): OrderInfo {
|
||||
const hash = getPackedHash(hexUtils.leftPad(order.salt));
|
||||
const orderStatus = order.salt.mod(255).eq(0) ? 3 : 5;
|
||||
const filledAmount = order.expirationTimeSeconds;
|
||||
return {
|
||||
orderStatus,
|
||||
orderHash: hash,
|
||||
orderTakerAssetFilledAmount: filledAmount,
|
||||
};
|
||||
}
|
||||
|
||||
function createFillableOrderSalt(): BigNumber {
|
||||
return new BigNumber(hexUtils.concat(hexUtils.slice(hexUtils.random(), 0, -1), '0x01'));
|
||||
}
|
||||
|
||||
function createUnfillableOrderSalt(): BigNumber {
|
||||
return new BigNumber(hexUtils.concat(hexUtils.slice(hexUtils.random(), 0, -1), '0xff'));
|
||||
}
|
||||
|
||||
function getOrderFillableTakerAmount(order: Order): BigNumber {
|
||||
return order.takerAssetAmount.minus(getOrderInfo(order).orderTakerAssetFilledAmount);
|
||||
}
|
||||
|
||||
function getERC20AssetData(tokenAddress: string): string {
|
||||
return hexUtils.concat(ERC20_PROXY_ID, hexUtils.leftPad(tokenAddress));
|
||||
}
|
||||
|
||||
function createOrder(fields: Partial<Order> = {}, filledTakerAssetAmount: BigNumber = ZERO_AMOUNT): Order {
|
||||
return {
|
||||
chainId: 1337,
|
||||
exchangeAddress: randomAddress(),
|
||||
makerAddress: randomAddress(),
|
||||
takerAddress: randomAddress(),
|
||||
senderAddress: randomAddress(),
|
||||
feeRecipientAddress: randomAddress(),
|
||||
makerAssetAmount: getRandomInteger(1e18, 10e18),
|
||||
takerAssetAmount: getRandomInteger(1e18, 10e18),
|
||||
makerFee: getRandomInteger(1e18, 10e18),
|
||||
takerFee: getRandomInteger(1e18, 10e18),
|
||||
makerAssetData: getERC20AssetData(makerToken),
|
||||
takerAssetData: getERC20AssetData(takerToken),
|
||||
makerFeeAssetData: getERC20AssetData(feeToken),
|
||||
takerFeeAssetData: getERC20AssetData(randomAddress()),
|
||||
salt: createFillableOrderSalt(),
|
||||
// Expiration time will be used to determine filled amount.
|
||||
expirationTimeSeconds: filledTakerAssetAmount,
|
||||
...fields,
|
||||
};
|
||||
}
|
||||
|
||||
async function fundMakerAsync(
|
||||
order: Order,
|
||||
assetData: string,
|
||||
balanceScaling: number = 1,
|
||||
allowanceScaling: number = 1,
|
||||
): Promise<void> {
|
||||
let token;
|
||||
let amount;
|
||||
if (assetData === order.makerAssetData) {
|
||||
token = makerToken;
|
||||
amount =
|
||||
order.makerAssetData === order.makerFeeAssetData
|
||||
? order.makerAssetAmount.plus(order.makerFee)
|
||||
: order.makerAssetAmount;
|
||||
} else {
|
||||
token = feeToken;
|
||||
amount = order.makerFee;
|
||||
}
|
||||
amount = amount.times(getOrderFillableTakerAmount(order).div(BigNumber.max(1, order.takerAssetAmount)));
|
||||
await testContract
|
||||
.setTokenBalanceAndAllowance(
|
||||
token,
|
||||
order.makerAddress,
|
||||
erc20Proxy,
|
||||
amount.times(balanceScaling).integerValue(),
|
||||
amount.times(allowanceScaling).integerValue(),
|
||||
)
|
||||
.awaitTransactionSuccessAsync();
|
||||
}
|
||||
|
||||
describe('getOrderFillableTakerAmount()', () => {
|
||||
it('returns the full amount for a fully funded order', async () => {
|
||||
const order = createOrder();
|
||||
const expected = getOrderFillableTakerAmount(order);
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
expect(actual).to.bignumber.eq(expected);
|
||||
});
|
||||
|
||||
it('returns the full amount for a fully funded order without maker fees', async () => {
|
||||
const order = createOrder({ makerFee: ZERO_AMOUNT });
|
||||
const expected = getOrderFillableTakerAmount(order);
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
expect(actual).to.bignumber.eq(expected);
|
||||
});
|
||||
|
||||
it('returns the full amount for a fully funded order without maker fee asset data', async () => {
|
||||
const order = createOrder({ makerFeeAssetData: NULL_BYTES });
|
||||
const expected = getOrderFillableTakerAmount(order);
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
expect(actual).to.bignumber.eq(expected);
|
||||
});
|
||||
|
||||
it('returns the full amount for a fully funded order with maker fees denominated in the maker asset', async () => {
|
||||
const order = createOrder({ makerFeeAssetData: getERC20AssetData(makerToken) });
|
||||
const expected = getOrderFillableTakerAmount(order);
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
expect(actual).to.bignumber.eq(expected);
|
||||
});
|
||||
|
||||
it('returns partial amount with insufficient maker asset balance', async () => {
|
||||
const order = createOrder();
|
||||
const expected = getOrderFillableTakerAmount(order)
|
||||
.times(0.5)
|
||||
.integerValue(BigNumber.ROUND_DOWN);
|
||||
await fundMakerAsync(order, order.makerAssetData, 0.5);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
assertIntegerRoughlyEquals(actual, expected, 100);
|
||||
});
|
||||
|
||||
it('returns partial amount with insufficient maker asset allowance', async () => {
|
||||
const order = createOrder();
|
||||
const expected = getOrderFillableTakerAmount(order)
|
||||
.times(0.5)
|
||||
.integerValue(BigNumber.ROUND_DOWN);
|
||||
await fundMakerAsync(order, order.makerAssetData, 1, 0.5);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
assertIntegerRoughlyEquals(actual, expected, 100);
|
||||
});
|
||||
|
||||
it('returns partial amount with insufficient maker fee asset balance', async () => {
|
||||
const order = createOrder();
|
||||
const expected = getOrderFillableTakerAmount(order)
|
||||
.times(0.5)
|
||||
.integerValue(BigNumber.ROUND_DOWN);
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData, 0.5);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
assertIntegerRoughlyEquals(actual, expected, 100);
|
||||
});
|
||||
|
||||
it('returns partial amount with insufficient maker fee asset allowance', async () => {
|
||||
const order = createOrder();
|
||||
const expected = getOrderFillableTakerAmount(order)
|
||||
.times(0.5)
|
||||
.integerValue(BigNumber.ROUND_DOWN);
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData, 1, 0.5);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
assertIntegerRoughlyEquals(actual, expected, 100);
|
||||
});
|
||||
|
||||
it('returns partial amount with insufficient maker asset balance (maker asset fees)', async () => {
|
||||
const order = createOrder({ makerFeeAssetData: getERC20AssetData(makerToken) });
|
||||
const expected = getOrderFillableTakerAmount(order)
|
||||
.times(0.5)
|
||||
.integerValue(BigNumber.ROUND_DOWN);
|
||||
await fundMakerAsync(order, order.makerAssetData, 0.5);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
assertIntegerRoughlyEquals(actual, expected, 100);
|
||||
});
|
||||
|
||||
it('returns partial amount with insufficient maker asset allowance (maker asset fees)', async () => {
|
||||
const order = createOrder({ makerFeeAssetData: getERC20AssetData(makerToken) });
|
||||
const expected = getOrderFillableTakerAmount(order)
|
||||
.times(0.5)
|
||||
.integerValue(BigNumber.ROUND_DOWN);
|
||||
await fundMakerAsync(order, order.makerAssetData, 1, 0.5);
|
||||
const actual = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
assertIntegerRoughlyEquals(actual, expected, 100);
|
||||
});
|
||||
|
||||
it('returns zero for an that is not fillable', async () => {
|
||||
const order = {
|
||||
...createOrder(),
|
||||
salt: createUnfillableOrderSalt(),
|
||||
};
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const fillableTakerAmount = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('returns zero for an order with zero maker asset amount', async () => {
|
||||
const order = {
|
||||
...createOrder(),
|
||||
makerAssetAmount: ZERO_AMOUNT,
|
||||
};
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const fillableTakerAmount = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('returns zero for an order with zero taker asset amount', async () => {
|
||||
const order = {
|
||||
...createOrder(),
|
||||
takerAssetAmount: ZERO_AMOUNT,
|
||||
};
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const fillableTakerAmount = await testContract
|
||||
.getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('returns zero for an order with an empty signature', async () => {
|
||||
const order = createOrder();
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const fillableTakerAmount = await testContract
|
||||
.getOrderFillableTakerAmount(order, NULL_BYTES, testContract.address)
|
||||
.callAsync();
|
||||
expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('returns zero for an order with an invalid signature', async () => {
|
||||
const order = createOrder();
|
||||
await fundMakerAsync(order, order.makerAssetData);
|
||||
await fundMakerAsync(order, order.makerFeeAssetData);
|
||||
const fillableTakerAmount = await testContract
|
||||
.getOrderFillableTakerAmount(order, INVALID_SIGNATURE, testContract.address)
|
||||
.callAsync();
|
||||
expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user