Add more verification test cases

This commit is contained in:
Amir Bandeali 2019-02-19 18:07:32 -05:00
parent 3c649df3df
commit 2de9b862d8
4 changed files with 437 additions and 187 deletions

View File

@ -1,4 +1,3 @@
import { artifacts as exchangeArtifacts, IExchangeContract } from '@0x/contracts-exchange';
import { import {
chaiSetup, chaiSetup,
constants as devConstants, constants as devConstants,
@ -18,6 +17,7 @@ import {
ApprovalFactory, ApprovalFactory,
artifacts, artifacts,
constants, constants,
exchangeDataEncoder,
hashUtils, hashUtils,
TECSignatureType, TECSignatureType,
TECTransactionFactory, TECTransactionFactory,
@ -29,34 +29,7 @@ const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const timeBuffer = new BigNumber(1000); const timeBuffer = new BigNumber(1000);
const encodeBatchOrderApproval = (fn: string, orders: SignedOrder[], exchangeInstance: IExchangeContract): string => { describe('Mixins tests', () => {
let data;
if (constants.BATCH_FILL_FN_NAMES.indexOf(fn) !== -1) {
data = (exchangeInstance as any)[fn].getABIEncodedTransactionData(
orders,
orders.map(order => order.takerAssetAmount),
orders.map(order => order.signature),
);
} else if (constants.MARKET_FILL_FN_NAMES.indexOf(fn) !== -1) {
data = (exchangeInstance as any)[fn].getABIEncodedTransactionData(
orders,
orders[0].takerAssetAmount,
orders.map(order => order.signature),
);
} else if (fn === 'matchOrders') {
data = (exchangeInstance as any)[fn].getABIEncodedTransactionData(
orders[0],
orders[1],
orders[0].signature,
orders[1].signature,
);
} else {
throw new Error(`Error: ${fn} not a batch fill function`);
}
return data;
};
describe.only('Mixins tests', () => {
let transactionSignerAddress: string; let transactionSignerAddress: string;
let approvalSignerAddress1: string; let approvalSignerAddress1: string;
let approvalSignerAddress2: string; let approvalSignerAddress2: string;
@ -65,7 +38,6 @@ describe.only('Mixins tests', () => {
let approvalFactory1: ApprovalFactory; let approvalFactory1: ApprovalFactory;
let approvalFactory2: ApprovalFactory; let approvalFactory2: ApprovalFactory;
let defaultOrder: SignedOrder; let defaultOrder: SignedOrder;
let exchangeInterface: IExchangeContract;
before(async () => { before(async () => {
await blockchainLifecycle.startAsync(); await blockchainLifecycle.startAsync();
}); });
@ -74,13 +46,8 @@ describe.only('Mixins tests', () => {
}); });
before(async () => { before(async () => {
mixins = await TestMixinsContract.deployFrom0xArtifactAsync(artifacts.TestMixins, provider, txDefaults); mixins = await TestMixinsContract.deployFrom0xArtifactAsync(artifacts.TestMixins, provider, txDefaults);
exchangeInterface = await IExchangeContract.deployFrom0xArtifactAsync(
exchangeArtifacts.IExchange,
provider,
txDefaults,
);
const accounts = await web3Wrapper.getAvailableAddressesAsync(); const accounts = await web3Wrapper.getAvailableAddressesAsync();
[transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts.slice(0, 2); [transactionSignerAddress, approvalSignerAddress1, approvalSignerAddress2] = accounts.slice(0, 3);
defaultOrder = { defaultOrder = {
exchangeAddress: devConstants.NULL_ADDRESS, exchangeAddress: devConstants.NULL_ADDRESS,
makerAddress: devConstants.NULL_ADDRESS, makerAddress: devConstants.NULL_ADDRESS,
@ -157,24 +124,20 @@ describe.only('Mixins tests', () => {
}); });
describe('Single order approvals', () => { describe('Single order approvals', () => {
for (const fn of constants.SINGLE_FILL_FN_NAMES) { for (const fnName of constants.SINGLE_FILL_FN_NAMES) {
it(`Should be successful: function=${fn}, caller=tx_signer, senderAddress=verifier, approval_sig=approver1, expiration=valid`, async () => { it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => {
const data = (exchangeInterface as any)[fn].getABIEncodedTransactionData( const orders = [defaultOrder];
defaultOrder, const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
defaultOrder.takerAssetAmount,
defaultOrder.signature,
);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidSingleOrderApproval.callAsync( await mixins.assertValidTransactionOrdersApproval.callAsync(
defaultOrder, transaction,
transactionHash, orders,
transaction.signature, transaction.signature,
approvalExpirationTimeSeconds, [approvalExpirationTimeSeconds],
approval.approvalSignature, [approval.approvalSignature],
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
); );
await mixins.assertValidTECApprovals.callAsync( await mixins.assertValidTECApprovals.callAsync(
@ -185,27 +148,23 @@ describe.only('Mixins tests', () => {
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
); );
}); });
it(`Should be successful: function=${fn}, caller=tx_signer, senderAddress=null, approval_sig=approver1, expiration=valid`, async () => { it(`Should be successful: function=${fnName}, caller=tx_signer, senderAddress=[null], approval_sig=[approver1], expiration=[valid]`, async () => {
const order = { const order = {
...defaultOrder, ...defaultOrder,
senderAddress: devConstants.NULL_ADDRESS, senderAddress: devConstants.NULL_ADDRESS,
}; };
const data = (exchangeInterface as any)[fn].getABIEncodedTransactionData( const orders = [order];
order, const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
order.takerAssetAmount,
order.signature,
);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidSingleOrderApproval.callAsync( await mixins.assertValidTransactionOrdersApproval.callAsync(
order, transaction,
transactionHash, orders,
transaction.signature, transaction.signature,
approvalExpirationTimeSeconds, [approvalExpirationTimeSeconds],
approval.approvalSignature, [approval.approvalSignature],
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
); );
await mixins.assertValidTECApprovals.callAsync( await mixins.assertValidTECApprovals.callAsync(
@ -216,88 +175,65 @@ describe.only('Mixins tests', () => {
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
); );
}); });
it(`Should be successful: function=${fn}, caller=approver1, senderAddress=verifier, approval_sig=null, expiration=valid`, async () => { it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[], expiration=[]`, async () => {
const data = (exchangeInterface as any)[fn].getABIEncodedTransactionData( const orders = [defaultOrder];
defaultOrder, const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
defaultOrder.takerAssetAmount,
defaultOrder.signature,
);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction); await mixins.assertValidTransactionOrdersApproval.callAsync(
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approvalSignature = devConstants.NULL_BYTES;
await mixins.assertValidSingleOrderApproval.callAsync(
defaultOrder,
transactionHash,
transaction.signature,
approvalExpirationTimeSeconds,
approvalSignature,
{ from: approvalSignerAddress1 },
);
await mixins.assertValidTECApprovals.callAsync(
transaction, transaction,
orders,
transaction.signature, transaction.signature,
[approvalExpirationTimeSeconds], [],
[approvalSignature], [],
{ from: approvalSignerAddress1 },
);
});
it(`Should be successful: function=${fn}, caller=approver1, senderAddress=verifier, approval_sig=approver1, expiration=invalid`, async () => {
const data = (exchangeInterface as any)[fn].getABIEncodedTransactionData(
defaultOrder,
defaultOrder.takerAssetAmount,
defaultOrder.signature,
);
const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidSingleOrderApproval.callAsync(
defaultOrder,
transactionHash,
transaction.signature,
approvalExpirationTimeSeconds,
approval.approvalSignature,
{ from: approvalSignerAddress1 },
);
await mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.approvalSignature],
{ from: approvalSignerAddress1 },
);
});
it(`Should be successful: function=${fn}, caller=approver1, senderAddress=verifier, approval_sig=null, expiration=null`, async () => {
const data = (exchangeInterface as any)[fn].getABIEncodedTransactionData(
defaultOrder,
defaultOrder.takerAssetAmount,
defaultOrder.signature,
);
const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
await mixins.assertValidSingleOrderApproval.callAsync(
defaultOrder,
transactionHash,
transaction.signature,
devConstants.ZERO_AMOUNT,
devConstants.NULL_BYTES,
{ from: approvalSignerAddress1 }, { from: approvalSignerAddress1 },
); );
await mixins.assertValidTECApprovals.callAsync(transaction, transaction.signature, [], [], { await mixins.assertValidTECApprovals.callAsync(transaction, transaction.signature, [], [], {
from: approvalSignerAddress1, from: approvalSignerAddress1,
}); });
}); });
it(`Should revert: function=${fn}, caller=tx_signer, senderAddress=verifier, approval_sig=invalid, expiration=valid`, async () => { it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => {
const data = (exchangeInterface as any)[fn].getABIEncodedTransactionData( const orders = [defaultOrder];
defaultOrder, const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
defaultOrder.takerAssetAmount, const transaction = transactionFactory.newSignedTECTransaction(data);
defaultOrder.signature, const currentTimestamp = await getLatestBlockTimestampAsync();
); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.approvalSignature],
{ from: approvalSignerAddress1 },
);
await mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.approvalSignature],
{ from: approvalSignerAddress1 },
);
});
it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
await mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[],
[],
{ from: approvalSignerAddress1 },
);
await mixins.assertValidTECApprovals.callAsync(transaction, transaction.signature, [], [], {
from: approvalSignerAddress1,
});
});
it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[invalid], expiration=[valid]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
@ -306,12 +242,12 @@ describe.only('Mixins tests', () => {
4, 4,
)}FFFFFFFF${approval.approvalSignature.slice(12)}`; )}FFFFFFFF${approval.approvalSignature.slice(12)}`;
expectContractCallFailedAsync( expectContractCallFailedAsync(
mixins.assertValidSingleOrderApproval.callAsync( mixins.assertValidTransactionOrdersApproval.callAsync(
defaultOrder, transaction,
transactionHash, orders,
transaction.signature, transaction.signature,
approvalExpirationTimeSeconds, [approvalExpirationTimeSeconds],
approvalSignature, [approvalSignature],
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
), ),
RevertReason.InvalidApprovalSignature, RevertReason.InvalidApprovalSignature,
@ -327,24 +263,20 @@ describe.only('Mixins tests', () => {
RevertReason.InvalidApprovalSignature, RevertReason.InvalidApprovalSignature,
); );
}); });
it(`Should revert: function=${fn}, caller=tx_signer, senderAddress=verifier, approval_sig=approver1, expiration=invalid`, async () => { it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => {
const data = (exchangeInterface as any)[fn].getABIEncodedTransactionData( const orders = [defaultOrder];
defaultOrder, const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
defaultOrder.takerAssetAmount,
defaultOrder.signature,
);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
expectContractCallFailedAsync( expectContractCallFailedAsync(
mixins.assertValidSingleOrderApproval.callAsync( mixins.assertValidTransactionOrdersApproval.callAsync(
defaultOrder, transaction,
transactionHash, orders,
transaction.signature, transaction.signature,
approvalExpirationTimeSeconds, [approvalExpirationTimeSeconds],
approval.approvalSignature, [approval.approvalSignature],
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
), ),
RevertReason.ApprovalExpired, RevertReason.ApprovalExpired,
@ -360,21 +292,53 @@ describe.only('Mixins tests', () => {
RevertReason.ApprovalExpired, RevertReason.ApprovalExpired,
); );
}); });
it(`Should revert: function=${fnName}, caller=approver2, senderAddress=[verifier], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
expectContractCallFailedAsync(
mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.approvalSignature],
{ from: approvalSignerAddress2 },
),
RevertReason.InvalidSender,
);
expectContractCallFailedAsync(
mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval.approvalSignature],
{ from: approvalSignerAddress2 },
),
RevertReason.InvalidSender,
);
});
} }
}); });
describe('Batch order approvals', () => { describe('Batch order approvals', () => {
for (const fn of [...constants.BATCH_FILL_FN_NAMES, ...constants.MARKET_FILL_FN_NAMES, 'matchOrders']) { for (const fnName of [
it(`Should be successful: function=${fn} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => { ...constants.BATCH_FILL_FN_NAMES,
...constants.MARKET_FILL_FN_NAMES,
constants.MATCH_ORDERS,
]) {
it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder, defaultOrder]; const orders = [defaultOrder, defaultOrder];
const data = encodeBatchOrderApproval(fn, orders, exchangeInterface); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidBatchOrderApproval.callAsync( await mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders, orders,
transactionHash,
transaction.signature, transaction.signature,
[approvalExpirationTimeSeconds], [approvalExpirationTimeSeconds],
[approval.approvalSignature], [approval.approvalSignature],
@ -388,20 +352,19 @@ describe.only('Mixins tests', () => {
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
); );
}); });
it(`Should be successful: function=${fn} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => { it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder, defaultOrder].map(order => ({ const orders = [defaultOrder, defaultOrder].map(order => ({
...order, ...order,
senderAddress: devConstants.NULL_ADDRESS, senderAddress: devConstants.NULL_ADDRESS,
})); }));
const data = encodeBatchOrderApproval(fn, orders, exchangeInterface); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidBatchOrderApproval.callAsync( await mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders, orders,
transactionHash,
transaction.signature, transaction.signature,
[approvalExpirationTimeSeconds], [approvalExpirationTimeSeconds],
[approval.approvalSignature], [approval.approvalSignature],
@ -415,17 +378,16 @@ describe.only('Mixins tests', () => {
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
); );
}); });
it(`Should be successful: function=${fn} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => { it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[null,null], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder, defaultOrder].map(order => ({ const orders = [defaultOrder, defaultOrder].map(order => ({
...order, ...order,
senderAddress: devConstants.NULL_ADDRESS, senderAddress: devConstants.NULL_ADDRESS,
})); }));
const data = encodeBatchOrderApproval(fn, orders, exchangeInterface); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction); await mixins.assertValidTransactionOrdersApproval.callAsync(
await mixins.assertValidBatchOrderApproval.callAsync( transaction,
orders, orders,
transactionHash,
transaction.signature, transaction.signature,
[], [],
[], [],
@ -435,17 +397,16 @@ describe.only('Mixins tests', () => {
from: transactionSignerAddress, from: transactionSignerAddress,
}); });
}); });
it(`Should be successful: function=${fn} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => { it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, senderAddress: devConstants.NULL_ADDRESS }]; const orders = [defaultOrder, { ...defaultOrder, senderAddress: devConstants.NULL_ADDRESS }];
const data = encodeBatchOrderApproval(fn, orders, exchangeInterface); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidBatchOrderApproval.callAsync( await mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders, orders,
transactionHash,
transaction.signature, transaction.signature,
[approvalExpirationTimeSeconds], [approvalExpirationTimeSeconds],
[approval.approvalSignature], [approval.approvalSignature],
@ -459,18 +420,17 @@ describe.only('Mixins tests', () => {
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
); );
}); });
it(`Should be successful: function=${fn} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver1,approver2], expiration=[valid,valid]`, async () => { it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver1,approver2], expiration=[valid,valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = encodeBatchOrderApproval(fn, orders, exchangeInterface); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidBatchOrderApproval.callAsync( await mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders, orders,
transactionHash,
transaction.signature, transaction.signature,
[approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds],
[approval1.approvalSignature, approval2.approvalSignature], [approval1.approvalSignature, approval2.approvalSignature],
@ -484,14 +444,13 @@ describe.only('Mixins tests', () => {
{ from: transactionSignerAddress }, { from: transactionSignerAddress },
); );
}); });
it(`Should be successful: function=${fn} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => { it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver1], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder, defaultOrder]; const orders = [defaultOrder, defaultOrder];
const data = encodeBatchOrderApproval(fn, orders, exchangeInterface); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction); await mixins.assertValidTransactionOrdersApproval.callAsync(
await mixins.assertValidBatchOrderApproval.callAsync( transaction,
orders, orders,
transactionHash,
transaction.signature, transaction.signature,
[], [],
[], [],
@ -501,17 +460,16 @@ describe.only('Mixins tests', () => {
from: approvalSignerAddress1, from: approvalSignerAddress1,
}); });
}); });
it(`Should be successful: function=${fn} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2], expiration=[valid]`, async () => { it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2], expiration=[valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = encodeBatchOrderApproval(fn, orders, exchangeInterface); const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data); const transaction = transactionFactory.newSignedTECTransaction(data);
const transactionHash = hashUtils.getTransactionHashHex(transaction);
const currentTimestamp = await getLatestBlockTimestampAsync(); const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds); const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds);
await mixins.assertValidBatchOrderApproval.callAsync( await mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders, orders,
transactionHash,
transaction.signature, transaction.signature,
[approvalExpirationTimeSeconds], [approvalExpirationTimeSeconds],
[approval2.approvalSignature], [approval2.approvalSignature],
@ -525,7 +483,243 @@ describe.only('Mixins tests', () => {
{ from: approvalSignerAddress1 }, { from: approvalSignerAddress1 },
); );
}); });
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[], expiration=[]`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
expectContractCallFailedAsync(
mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[],
[],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
expectContractCallFailedAsync(
mixins.assertValidTECApprovals.callAsync(transaction, transaction.signature, [], [], {
from: transactionSignerAddress,
}),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[invalid], expiration=[valid]`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
const approvalSignature = `${approval.approvalSignature.slice(
0,
4,
)}FFFFFFFF${approval.approvalSignature.slice(12)}`;
expectContractCallFailedAsync(
mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[approvalExpirationTimeSeconds],
[approvalSignature],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
expectContractCallFailedAsync(
mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds],
[approvalSignature],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,invalid], expiration=[valid,valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds);
const approvalSignature2 = `${approval2.approvalSignature.slice(
0,
4,
)}FFFFFFFF${approval2.approvalSignature.slice(12)}`;
expectContractCallFailedAsync(
mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[approvalExpirationTimeSeconds, approvalExpirationTimeSeconds],
[approval1.approvalSignature, approvalSignature2],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
expectContractCallFailedAsync(
mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds, approvalExpirationTimeSeconds],
[approval1.approvalSignature, approvalSignature2],
{ from: transactionSignerAddress },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[invalid], expiration=[valid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds);
const approvalSignature2 = `${approval2.approvalSignature.slice(
0,
4,
)}FFFFFFFF${approval2.approvalSignature.slice(12)}`;
expectContractCallFailedAsync(
mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[approvalExpirationTimeSeconds],
[approvalSignature2],
{ from: approvalSignerAddress1 },
),
RevertReason.InvalidApprovalSignature,
);
expectContractCallFailedAsync(
mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds],
[approvalSignature2],
{ from: approvalSignerAddress1 },
),
RevertReason.InvalidApprovalSignature,
);
});
it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid,valid], expiration=[valid,invalid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds1 = new BigNumber(currentTimestamp).plus(timeBuffer);
const approvalExpirationTimeSeconds2 = new BigNumber(currentTimestamp).minus(timeBuffer);
const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds1);
const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds2);
expectContractCallFailedAsync(
mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2],
[approval1.approvalSignature, approval2.approvalSignature],
{ from: transactionSignerAddress },
),
RevertReason.ApprovalExpired,
);
expectContractCallFailedAsync(
mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2],
[approval1.approvalSignature, approval2.approvalSignature],
{ from: transactionSignerAddress },
),
RevertReason.ApprovalExpired,
);
});
it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver2], approval_sig=[valid], expiration=[invalid]`, async () => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(timeBuffer);
const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds);
expectContractCallFailedAsync(
mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval2.approvalSignature],
{ from: approvalSignerAddress1 },
),
RevertReason.ApprovalExpired,
);
expectContractCallFailedAsync(
mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval2.approvalSignature],
{ from: approvalSignerAddress1 },
),
RevertReason.ApprovalExpired,
);
});
it(`Should revert: function=${fnName} caller=approver2, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[valid], expiration=[valid]`, async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
const currentTimestamp = await getLatestBlockTimestampAsync();
const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(timeBuffer);
const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds);
expectContractCallFailedAsync(
mixins.assertValidTransactionOrdersApproval.callAsync(
transaction,
orders,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval1.approvalSignature],
{ from: approvalSignerAddress2 },
),
RevertReason.InvalidSender,
);
expectContractCallFailedAsync(
mixins.assertValidTECApprovals.callAsync(
transaction,
transaction.signature,
[approvalExpirationTimeSeconds],
[approval1.approvalSignature],
{ from: approvalSignerAddress2 },
),
RevertReason.InvalidSender,
);
});
} }
}); });
describe('assertValidTECApprovals', () => {}); describe('cancels', () => {
it('should allow the tx signer to call `cancelOrders` without approval', async () => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.CANCEL_ORDERS, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
await mixins.assertValidTECApprovals.callAsync(transaction, transaction.signature, [], [], {
from: transactionSignerAddress,
});
});
it('should allow the tx signer to call `batchCancelOrders` without approval', async () => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.BATCH_CANCEL_ORDERS, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
await mixins.assertValidTECApprovals.callAsync(transaction, transaction.signature, [], [], {
from: transactionSignerAddress,
});
});
it('should allow the tx signer to call `cancelOrdersUpTo` without approval', async () => {
const orders: SignedOrder[] = [];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.CANCEL_ORDERS_UP_TO, orders);
const transaction = transactionFactory.newSignedTECTransaction(data);
await mixins.assertValidTECApprovals.callAsync(transaction, transaction.signature, [], [], {
from: transactionSignerAddress,
});
});
});
}); });

View File

@ -12,4 +12,8 @@ export const constants = {
SINGLE_FILL_FN_NAMES: ['fillOrder', 'fillOrKillOrder', 'fillOrderNoThrow'], SINGLE_FILL_FN_NAMES: ['fillOrder', 'fillOrKillOrder', 'fillOrderNoThrow'],
BATCH_FILL_FN_NAMES: ['batchFillOrders', 'batchFillOrKillOrders', 'batchFillOrdersNoThrow'], BATCH_FILL_FN_NAMES: ['batchFillOrders', 'batchFillOrKillOrders', 'batchFillOrdersNoThrow'],
MARKET_FILL_FN_NAMES: ['marketBuyOrders', 'marketBuyOrdersNoThrow', 'marketSellOrders', 'marketSellOrdersNoThrow'], MARKET_FILL_FN_NAMES: ['marketBuyOrders', 'marketBuyOrdersNoThrow', 'marketSellOrders', 'marketSellOrdersNoThrow'],
MATCH_ORDERS: 'matchOrders',
CANCEL_ORDERS: 'cancelOrders',
BATCH_CANCEL_ORDERS: 'batchCancelOrders',
CANCEL_ORDERS_UP_TO: 'cancelOrdersUpTo',
}; };

View File

@ -0,0 +1,51 @@
import { artifacts, IExchangeContract } from '@0x/contracts-exchange';
import { constants as devConstants, provider } from '@0x/contracts-test-utils';
import { SignedOrder } from '@0x/types';
import { constants } from './index';
export const exchangeDataEncoder = {
encodeOrdersToExchangeData(fnName: string, orders: SignedOrder[]): string {
const exchangeInstance = new IExchangeContract(
artifacts.IExchange.compilerOutput.abi,
devConstants.NULL_ADDRESS,
provider,
);
let data;
if (constants.SINGLE_FILL_FN_NAMES.indexOf(fnName) !== -1) {
data = (exchangeInstance as any)[fnName].getABIEncodedTransactionData(
orders[0],
orders[0].takerAssetAmount,
orders[0].signature,
);
} else if (constants.BATCH_FILL_FN_NAMES.indexOf(fnName) !== -1) {
data = (exchangeInstance as any)[fnName].getABIEncodedTransactionData(
orders,
orders.map(order => order.takerAssetAmount),
orders.map(order => order.signature),
);
} else if (constants.MARKET_FILL_FN_NAMES.indexOf(fnName) !== -1) {
data = (exchangeInstance as any)[fnName].getABIEncodedTransactionData(
orders,
orders[0].takerAssetAmount,
orders.map(order => order.signature),
);
} else if (fnName === constants.MATCH_ORDERS) {
data = exchangeInstance.matchOrders.getABIEncodedTransactionData(
orders[0],
orders[1],
orders[0].signature,
orders[1].signature,
);
} else if (fnName === constants.CANCEL_ORDERS) {
data = exchangeInstance.cancelOrder.getABIEncodedTransactionData(orders[0]);
} else if (fnName === constants.BATCH_CANCEL_ORDERS) {
data = exchangeInstance.batchCancelOrders.getABIEncodedTransactionData(orders);
} else if (fnName === constants.CANCEL_ORDERS_UP_TO) {
data = exchangeInstance.cancelOrdersUpTo.getABIEncodedTransactionData(devConstants.ZERO_AMOUNT);
} else {
throw new Error(`Error: ${fnName} not a supported function`);
}
return data;
},
};

View File

@ -3,4 +3,5 @@ export { signingUtils } from './signing_utils';
export { TECTransactionFactory } from './tec_transaction_factory'; export { TECTransactionFactory } from './tec_transaction_factory';
export { ApprovalFactory } from './approval_factory'; export { ApprovalFactory } from './approval_factory';
export { constants } from './constants'; export { constants } from './constants';
export { exchangeDataEncoder } from './exchange_data_encoder';
export * from './types'; export * from './types';