298 lines
8.7 KiB
TypeScript
298 lines
8.7 KiB
TypeScript
import {
|
|
addressUtils,
|
|
chaiSetup,
|
|
OrderStatus,
|
|
orderUtils,
|
|
provider,
|
|
txDefaults,
|
|
web3Wrapper,
|
|
} from '@0x/contracts-test-utils';
|
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
|
import { ExchangeRevertErrors, generatePseudoRandomSalt } from '@0x/order-utils';
|
|
import { RevertError } from '@0x/utils';
|
|
import * as chai from 'chai';
|
|
import * as crypto from 'crypto';
|
|
import * as _ from 'lodash';
|
|
|
|
import {
|
|
artifacts,
|
|
TestLibExchangeRichErrorDecoderContract,
|
|
} from '../src';
|
|
|
|
chaiSetup.configure();
|
|
const expect = chai.expect;
|
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
|
|
|
describe('LibExchangeRichErrorDecoder', () => {
|
|
const SIGNATURE_LENGTH = 66;
|
|
const ASSET_DATA_LENGTH = 36;
|
|
const ERROR_DATA_LENGTH = 100;
|
|
let decoder: TestLibExchangeRichErrorDecoderContract;
|
|
|
|
before(async () => {
|
|
await blockchainLifecycle.startAsync();
|
|
});
|
|
after(async () => {
|
|
await blockchainLifecycle.revertAsync();
|
|
});
|
|
before(async () => {
|
|
decoder = await TestLibExchangeRichErrorDecoderContract.deployFrom0xArtifactAsync(
|
|
artifacts.TestLibExchangeRichErrorDecoder,
|
|
provider,
|
|
txDefaults,
|
|
);
|
|
});
|
|
|
|
function generateRandomBytes(length: number): string {
|
|
const bytes = crypto.randomBytes(length).toString('hex');
|
|
return `0x${bytes}`;
|
|
}
|
|
|
|
function createDecodeTest(
|
|
revertType: new(...args: any[]) => RevertError,
|
|
parameters: any[],
|
|
) {
|
|
const revert = new revertType(...parameters);
|
|
const encoded = revert.encode();
|
|
// Exploit the fact that `RevertError` types have the same names as their
|
|
// Solidity counterparts.
|
|
const endpointName = `decode${revert.name}`;
|
|
const callAsync = (encoded: string) => {
|
|
return (decoder as any)[endpointName].callAsync.call(
|
|
(decoder as any)[endpointName],
|
|
encoded,
|
|
);
|
|
};
|
|
describe(`${endpointName}()`, async () => {
|
|
it('decodes encoded parameters', async () => {
|
|
let results = await callAsync(encoded);
|
|
if (!_.isArray(results)) {
|
|
results = [results];
|
|
}
|
|
return expect(results).to.deep.equal(parameters);
|
|
});
|
|
it('reverts if selector does not match', async () => {
|
|
// Replace the selector with null bytes.
|
|
const NULL_SELECTOR = '00000000';
|
|
const withBadSelector = `0x${NULL_SELECTOR}${encoded.substr(10)}`;
|
|
return expect(callAsync(withBadSelector)).to.revertWith('BAD_SELECTOR');
|
|
});
|
|
});
|
|
};
|
|
|
|
(() => {
|
|
const errorCode = ExchangeRevertErrors.SignatureErrorCode.Illegal;
|
|
const orderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
const signer = addressUtils.generatePseudoRandomAddress();
|
|
const signature = generateRandomBytes(SIGNATURE_LENGTH);
|
|
const errorData = generateRandomBytes(ERROR_DATA_LENGTH);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.SignatureError,
|
|
[
|
|
errorCode,
|
|
orderHash,
|
|
signer,
|
|
signature,
|
|
],
|
|
);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.SignatureValidatorError,
|
|
[
|
|
orderHash,
|
|
signer,
|
|
signature,
|
|
errorData,
|
|
],
|
|
);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.SignatureWalletError,
|
|
[
|
|
orderHash,
|
|
signer,
|
|
signature,
|
|
errorData,
|
|
],
|
|
);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.SignatureOrderValidatorError,
|
|
[
|
|
orderHash,
|
|
signer,
|
|
signature,
|
|
errorData,
|
|
],
|
|
);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.SignatureWalletOrderValidatorError,
|
|
[
|
|
orderHash,
|
|
signer,
|
|
signature,
|
|
errorData,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const orderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
const orderStatus = OrderStatus.FullyFilled;
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.OrderStatusError,
|
|
[
|
|
orderHash,
|
|
orderStatus,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const orderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
const address = addressUtils.generatePseudoRandomAddress();
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.InvalidSenderError,
|
|
[
|
|
orderHash,
|
|
address,
|
|
],
|
|
);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.InvalidMakerError,
|
|
[
|
|
orderHash,
|
|
address,
|
|
],
|
|
);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.InvalidTakerError,
|
|
[
|
|
orderHash,
|
|
address,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const errorCode = ExchangeRevertErrors.FillErrorCode.TakerOverpay;
|
|
const orderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.FillError,
|
|
[
|
|
errorCode,
|
|
orderHash,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const maker = addressUtils.generatePseudoRandomAddress();
|
|
const sender = addressUtils.generatePseudoRandomAddress();
|
|
const currentEpoch = generatePseudoRandomSalt();
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.OrderEpochError,
|
|
[
|
|
maker,
|
|
sender,
|
|
currentEpoch,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const assetProxyAddress = addressUtils.generatePseudoRandomAddress();
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.AssetProxyExistsError,
|
|
[
|
|
assetProxyAddress,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const errorCode = ExchangeRevertErrors.AssetProxyDispatchErrorCode.UnknownAssetProxy;
|
|
const orderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
const assetData = generateRandomBytes(ASSET_DATA_LENGTH);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.AssetProxyDispatchError,
|
|
[
|
|
errorCode,
|
|
orderHash,
|
|
assetData,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const orderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
const assetData = generateRandomBytes(ASSET_DATA_LENGTH);
|
|
const errorData = generateRandomBytes(ERROR_DATA_LENGTH);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.AssetProxyTransferError,
|
|
[
|
|
orderHash,
|
|
assetData,
|
|
errorData,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const leftOrderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
const rightOrderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.NegativeSpreadError,
|
|
[
|
|
leftOrderHash,
|
|
rightOrderHash,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const errorCode = ExchangeRevertErrors.TransactionErrorCode.AlreadyExecuted;
|
|
const transactionHash = orderUtils.generatePseudoRandomOrderHash();
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.TransactionError,
|
|
[
|
|
errorCode,
|
|
transactionHash,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const transactionHash = orderUtils.generatePseudoRandomOrderHash();
|
|
const signer = addressUtils.generatePseudoRandomAddress();
|
|
const signature = generateRandomBytes(SIGNATURE_LENGTH);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.TransactionSignatureError,
|
|
[
|
|
transactionHash,
|
|
signer,
|
|
signature,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const transactionHash = orderUtils.generatePseudoRandomOrderHash();
|
|
const errorData = generateRandomBytes(ERROR_DATA_LENGTH);
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.TransactionExecutionError,
|
|
[
|
|
transactionHash,
|
|
errorData,
|
|
],
|
|
);
|
|
})();
|
|
|
|
(() => {
|
|
const orderHash = orderUtils.generatePseudoRandomOrderHash();
|
|
createDecodeTest(
|
|
ExchangeRevertErrors.IncompleteFillError,
|
|
[
|
|
orderHash,
|
|
],
|
|
);
|
|
})();
|
|
});
|