* move orderParsingUtils from order-utils to connect * Remove many functions from signatureUtils Removed from the exported object, that is. All of them are used in other existing code, so they were all moved to be as local to their usage as possible. * remove orderHashUtils.isValidOrderHash() * Move all *RevertErrors from order-utils... ...into their respective @0x/contracts- packages. * Refactor @0x/order-utils' orderHashUtils away - Move existing routines into @0x/contracts-test-utils - Migrate non-contract-test callers to a newly-exposed getOrderHash() method in DevUtils. * Move all *RevertErrors from @0x/utils... ...into their respective @0x/contracts- packages. * rm transactionHashUtils.isValidTransactionHash() * DevUtils.sol: Fail yarn test if too big to deploy * Refactor @0x/order-utils transactionHashUtils away - Move existing routines into @0x/contracts-test-utils - Migrate non-contract-test callers to a newly-exposed getTransactionHash() method in DevUtils. * Consolidate `Removed export...` CHANGELOG entries * Rm EthBalanceChecker from devutils wrapper exports * Stop importing from '.' or '.../src' * fix builds * fix prettier; dangling promise * increase max bundle size
539 lines
32 KiB
TypeScript
539 lines
32 KiB
TypeScript
import { exchangeDataEncoder } from '@0x/contracts-exchange';
|
|
import {
|
|
blockchainTests,
|
|
constants,
|
|
ExchangeFunctionName,
|
|
expect,
|
|
hexConcat,
|
|
hexSlice,
|
|
randomAddress,
|
|
TransactionFactory,
|
|
transactionHashUtils,
|
|
} from '@0x/contracts-test-utils';
|
|
import { LibBytesRevertErrors } from '@0x/contracts-utils';
|
|
import { SignatureType, SignedOrder } from '@0x/types';
|
|
import { BigNumber } from '@0x/utils';
|
|
|
|
import CoordinatorRevertErrors = require('../src/revert_errors');
|
|
|
|
import { ApprovalFactory } from '../src/approval_factory';
|
|
|
|
import { artifacts } from './artifacts';
|
|
|
|
import { CoordinatorContract } from './wrappers';
|
|
|
|
blockchainTests.resets('Mixins tests', env => {
|
|
let chainId: number;
|
|
let transactionSignerAddress: string;
|
|
let approvalSignerAddress1: string;
|
|
let approvalSignerAddress2: string;
|
|
let mixins: CoordinatorContract;
|
|
let transactionFactory: TransactionFactory;
|
|
let approvalFactory1: ApprovalFactory;
|
|
let approvalFactory2: ApprovalFactory;
|
|
let defaultOrder: SignedOrder;
|
|
const exchangeAddress = randomAddress();
|
|
|
|
before(async () => {
|
|
chainId = await env.getChainIdAsync();
|
|
mixins = await CoordinatorContract.deployFrom0xArtifactAsync(
|
|
artifacts.Coordinator,
|
|
env.provider,
|
|
env.txDefaults,
|
|
artifacts,
|
|
exchangeAddress,
|
|
new BigNumber(chainId),
|
|
);
|
|
const accounts = await env.getAccountAddressesAsync();
|
|
[transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts;
|
|
defaultOrder = {
|
|
makerAddress: constants.NULL_ADDRESS,
|
|
takerAddress: constants.NULL_ADDRESS,
|
|
senderAddress: mixins.address,
|
|
feeRecipientAddress: approvalSignerAddress1,
|
|
makerAssetData: constants.NULL_BYTES,
|
|
takerAssetData: constants.NULL_BYTES,
|
|
makerAssetAmount: constants.ZERO_AMOUNT,
|
|
takerAssetAmount: constants.ZERO_AMOUNT,
|
|
makerFee: constants.ZERO_AMOUNT,
|
|
takerFee: constants.ZERO_AMOUNT,
|
|
makerFeeAssetData: constants.NULL_BYTES,
|
|
takerFeeAssetData: constants.NULL_BYTES,
|
|
expirationTimeSeconds: constants.ZERO_AMOUNT,
|
|
salt: constants.ZERO_AMOUNT,
|
|
signature: constants.NULL_BYTES,
|
|
exchangeAddress: constants.NULL_ADDRESS,
|
|
chainId,
|
|
};
|
|
const transactionSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(transactionSignerAddress)];
|
|
const approvalSignerPrivateKey1 = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(approvalSignerAddress1)];
|
|
const approvalSignerPrivateKey2 = constants.TESTRPC_PRIVATE_KEYS[accounts.indexOf(approvalSignerAddress2)];
|
|
transactionFactory = new TransactionFactory(transactionSignerPrivateKey, exchangeAddress, chainId);
|
|
approvalFactory1 = new ApprovalFactory(approvalSignerPrivateKey1, mixins.address);
|
|
approvalFactory2 = new ApprovalFactory(approvalSignerPrivateKey2, mixins.address);
|
|
});
|
|
|
|
describe('getSignerAddress', () => {
|
|
it('should return the correct address using the EthSign signature type', async () => {
|
|
const data = constants.NULL_BYTES;
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data }, SignatureType.EthSign);
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
const signerAddress = await mixins.getSignerAddress(transactionHash, transaction.signature).callAsync();
|
|
expect(transaction.signerAddress).to.eq(signerAddress);
|
|
});
|
|
it('should return the correct address using the EIP712 signature type', async () => {
|
|
const data = constants.NULL_BYTES;
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data }, SignatureType.EIP712);
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
const signerAddress = await mixins.getSignerAddress(transactionHash, transaction.signature).callAsync();
|
|
expect(transaction.signerAddress).to.eq(signerAddress);
|
|
});
|
|
it('should revert with with the Illegal signature type', async () => {
|
|
const data = constants.NULL_BYTES;
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
transaction.signature = hexConcat(
|
|
hexSlice(transaction.signature, 0, transaction.signature.length - 1),
|
|
SignatureType.Illegal,
|
|
);
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
|
|
new CoordinatorRevertErrors.SignatureError(
|
|
CoordinatorRevertErrors.SignatureErrorCodes.Illegal,
|
|
transactionHash,
|
|
transaction.signature,
|
|
),
|
|
);
|
|
});
|
|
it('should revert with with the Invalid signature type', async () => {
|
|
const data = constants.NULL_BYTES;
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
transaction.signature = hexConcat(SignatureType.Invalid);
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
|
|
new CoordinatorRevertErrors.SignatureError(
|
|
CoordinatorRevertErrors.SignatureErrorCodes.Invalid,
|
|
transactionHash,
|
|
transaction.signature,
|
|
),
|
|
);
|
|
});
|
|
it('should revert with with a signature type that equals `NSignatureTypes`', async () => {
|
|
const data = constants.NULL_BYTES;
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
transaction.signature = hexConcat(
|
|
hexSlice(transaction.signature, 0, transaction.signature.length - 1),
|
|
SignatureType.NSignatureTypes,
|
|
);
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
|
|
new CoordinatorRevertErrors.SignatureError(
|
|
CoordinatorRevertErrors.SignatureErrorCodes.Unsupported,
|
|
transactionHash,
|
|
transaction.signature,
|
|
),
|
|
);
|
|
});
|
|
it("should revert with with a signature type that isn't supported", async () => {
|
|
const data = constants.NULL_BYTES;
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
transaction.signature = hexConcat(
|
|
hexSlice(transaction.signature, 0, transaction.signature.length - 1),
|
|
SignatureType.Wallet,
|
|
);
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(mixins.getSignerAddress(transactionHash, transaction.signature).callAsync()).to.revertWith(
|
|
new CoordinatorRevertErrors.SignatureError(
|
|
CoordinatorRevertErrors.SignatureErrorCodes.Unsupported,
|
|
transactionHash,
|
|
transaction.signature,
|
|
),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('decodeOrdersFromFillData', () => {
|
|
for (const fnName of constants.SINGLE_FILL_FN_NAMES) {
|
|
it(`should correctly decode the orders for ${fnName} data`, async () => {
|
|
const orders = [defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
|
|
const decodedSignedOrders = decodedOrders.map(order => ({
|
|
...order,
|
|
signature: constants.NULL_BYTES,
|
|
exchangeAddress: constants.NULL_ADDRESS,
|
|
chainId,
|
|
}));
|
|
expect(orders).to.deep.eq(decodedSignedOrders);
|
|
});
|
|
}
|
|
for (const fnName of constants.BATCH_FILL_FN_NAMES) {
|
|
it(`should correctly decode the orders for ${fnName} data`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
|
|
const decodedSignedOrders = decodedOrders.map(order => ({
|
|
...order,
|
|
signature: constants.NULL_BYTES,
|
|
exchangeAddress: constants.NULL_ADDRESS,
|
|
chainId,
|
|
}));
|
|
expect(orders).to.deep.eq(decodedSignedOrders);
|
|
});
|
|
}
|
|
for (const fnName of constants.MARKET_FILL_FN_NAMES) {
|
|
it(`should correctly decode the orders for ${fnName} data`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
|
|
const decodedSignedOrders = decodedOrders.map(order => ({
|
|
...order,
|
|
signature: constants.NULL_BYTES,
|
|
exchangeAddress: constants.NULL_ADDRESS,
|
|
chainId,
|
|
}));
|
|
expect(orders).to.deep.eq(decodedSignedOrders);
|
|
});
|
|
}
|
|
for (const fnName of constants.MATCH_ORDER_FN_NAMES) {
|
|
it(`should correctly decode the orders for ${fnName} data`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
|
|
const decodedSignedOrders = decodedOrders.map(order => ({
|
|
...order,
|
|
signature: constants.NULL_BYTES,
|
|
exchangeAddress: constants.NULL_ADDRESS,
|
|
chainId,
|
|
}));
|
|
expect(orders).to.deep.eq(decodedSignedOrders);
|
|
});
|
|
}
|
|
for (const fnName of constants.CANCEL_ORDER_FN_NAMES) {
|
|
it(`should correctly decode the orders for ${fnName} data`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
|
|
const emptyArray: any[] = [];
|
|
expect(emptyArray).to.deep.eq(decodedOrders);
|
|
});
|
|
}
|
|
it('should decode an empty array for invalid data', async () => {
|
|
const data = '0x0123456789';
|
|
const decodedOrders = await mixins.decodeOrdersFromFillData(data).callAsync();
|
|
const emptyArray: any[] = [];
|
|
expect(emptyArray).to.deep.eq(decodedOrders);
|
|
});
|
|
it('should revert if data is less than 4 bytes long', async () => {
|
|
const data = '0x010203';
|
|
const expectedError = new LibBytesRevertErrors.InvalidByteOperationError(
|
|
LibBytesRevertErrors.InvalidByteOperationErrorCodes.LengthGreaterThanOrEqualsFourRequired,
|
|
new BigNumber(3), // the length of data
|
|
new BigNumber(4),
|
|
);
|
|
return expect(mixins.decodeOrdersFromFillData(data).callAsync()).to.revertWith(expectedError);
|
|
});
|
|
});
|
|
|
|
describe('Single order approvals', () => {
|
|
for (const fnName of constants.SINGLE_FILL_FN_NAMES) {
|
|
it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1]`, async () => {
|
|
const orders = [defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval.signature,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[null], approval_sig=[approver1]`, async () => {
|
|
const order = {
|
|
...defaultOrder,
|
|
senderAddress: constants.NULL_ADDRESS,
|
|
};
|
|
const orders = [order];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval.signature,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[]`, async () => {
|
|
const orders = [defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [])
|
|
.callAsync({
|
|
from: approvalSignerAddress1,
|
|
});
|
|
});
|
|
it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[approver1]`, async () => {
|
|
const orders = [defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [
|
|
approval.signature,
|
|
])
|
|
.callAsync({ from: approvalSignerAddress1 });
|
|
});
|
|
it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[]`, async () => {
|
|
const orders = [defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [])
|
|
.callAsync({
|
|
from: approvalSignerAddress1,
|
|
});
|
|
});
|
|
it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[invalid]`, async () => {
|
|
const orders = [defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
const signature = hexConcat(
|
|
hexSlice(approval.signature, 0, 2),
|
|
'0xFFFFFFFF',
|
|
hexSlice(approval.signature, 6),
|
|
);
|
|
const tx = mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
signature,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(tx).to.revertWith(
|
|
new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1),
|
|
);
|
|
});
|
|
it(`Should revert: function=${fnName}, caller=approver2, senderAddress=[verifier], approval_sig=[approver1]`, async () => {
|
|
const orders = [defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
|
|
const tx = mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval.signature,
|
|
])
|
|
.callAsync({ from: approvalSignerAddress2 });
|
|
expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress));
|
|
});
|
|
}
|
|
});
|
|
describe('Batch order approvals', () => {
|
|
for (const fnName of [
|
|
...constants.BATCH_FILL_FN_NAMES,
|
|
...constants.MARKET_FILL_FN_NAMES,
|
|
...constants.MATCH_ORDER_FN_NAMES,
|
|
]) {
|
|
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval.signature,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => {
|
|
const orders = [defaultOrder, defaultOrder].map(order => ({
|
|
...order,
|
|
senderAddress: constants.NULL_ADDRESS,
|
|
}));
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval.signature,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[]`, async () => {
|
|
const orders = [defaultOrder, defaultOrder].map(order => ({
|
|
...order,
|
|
senderAddress: constants.NULL_ADDRESS,
|
|
}));
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1]`, async () => {
|
|
const orders = [defaultOrder, { ...defaultOrder, senderAddress: constants.NULL_ADDRESS }];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval.signature,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver1,approver2]`, async () => {
|
|
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval1.signature,
|
|
approval2.signature,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[]`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [])
|
|
.callAsync({ from: approvalSignerAddress1 });
|
|
});
|
|
it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2]`, async () => {
|
|
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
|
|
const tx = mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval2.signature,
|
|
])
|
|
.callAsync({ from: approvalSignerAddress1 });
|
|
expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress));
|
|
});
|
|
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[]`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const tx = mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(tx).to.revertWith(
|
|
new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1),
|
|
);
|
|
});
|
|
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[invalid]`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
const signature = hexConcat(
|
|
hexSlice(approval.signature, 0, 2),
|
|
'0xFFFFFFFF',
|
|
hexSlice(approval.signature, 6),
|
|
);
|
|
const tx = mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
signature,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(tx).to.revertWith(
|
|
new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress1),
|
|
);
|
|
});
|
|
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,invalid]`, async () => {
|
|
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
const approvalSignature2 = hexConcat(
|
|
hexSlice(approval2.signature, 0, 2),
|
|
'0xFFFFFFFF',
|
|
hexSlice(approval2.signature, 6),
|
|
);
|
|
const tx = mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval1.signature,
|
|
approvalSignature2,
|
|
])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(tx).to.revertWith(
|
|
new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress2),
|
|
);
|
|
});
|
|
it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[invalid]`, async () => {
|
|
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
const approvalSignature2 = hexConcat(
|
|
hexSlice(approval2.signature, 0, 2),
|
|
'0xFFFFFFFF',
|
|
hexSlice(approval2.signature, 6),
|
|
);
|
|
const tx = mixins
|
|
.assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [
|
|
approvalSignature2,
|
|
])
|
|
.callAsync({ from: approvalSignerAddress1 });
|
|
|
|
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
|
|
expect(tx).to.revertWith(
|
|
new CoordinatorRevertErrors.InvalidApprovalSignatureError(transactionHash, approvalSignerAddress2),
|
|
);
|
|
});
|
|
it(`Should revert: function=${fnName} caller=approver2, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[valid]`, async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
|
|
|
|
const tx = mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
|
|
approval1.signature,
|
|
])
|
|
.callAsync({ from: approvalSignerAddress2 });
|
|
expect(tx).to.revertWith(new CoordinatorRevertErrors.InvalidOriginError(transactionSignerAddress));
|
|
});
|
|
}
|
|
});
|
|
describe('cancels', () => {
|
|
it('should allow the tx signer to call `cancelOrder` without approval', async () => {
|
|
const orders = [defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrder, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it('should allow the tx signer to call `batchCancelOrders` without approval', async () => {
|
|
const orders = [defaultOrder, defaultOrder];
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.BatchCancelOrders, orders);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
it('should allow the tx signer to call `cancelOrdersUpTo` without approval', async () => {
|
|
const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrdersUpTo);
|
|
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
|
|
await mixins
|
|
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [])
|
|
.callAsync({ from: transactionSignerAddress });
|
|
});
|
|
});
|
|
});
|
|
// tslint:disable:max-file-line-count
|