* remove assetDataUtils everywhere * export IAssetDataContract from @0x/contract-wrappers to allow @0x/instant to decode asset data synchronously * export generic function `decodeAssetDataOrThrow` and add ERC20Bridge support * export `hexUtils` from order-utils instead of contracts-test-utils
		
			
				
	
	
		
			153 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { blockchainTests, constants, expect, OrderStatus, orderUtils, randomAddress } from '@0x/contracts-test-utils';
 | 
						|
import { generatePseudoRandomSalt } from '@0x/order-utils';
 | 
						|
import { BigNumber, ExchangeRevertErrors, hexUtils, RevertError } from '@0x/utils';
 | 
						|
import * as _ from 'lodash';
 | 
						|
 | 
						|
import { artifacts } from './artifacts';
 | 
						|
import { TestLibExchangeRichErrorDecoderContract } from './wrappers';
 | 
						|
 | 
						|
blockchainTests.resets('LibExchangeRichErrorDecoder', ({ provider, txDefaults }) => {
 | 
						|
    const ASSET_PROXY_ID_LENGTH = 4;
 | 
						|
    const SIGNATURE_LENGTH = 66;
 | 
						|
    const ASSET_DATA_LENGTH = 36;
 | 
						|
    const ERROR_DATA_LENGTH = 100;
 | 
						|
    const { WORD_LENGTH } = constants;
 | 
						|
    let decoder: TestLibExchangeRichErrorDecoderContract;
 | 
						|
 | 
						|
    before(async () => {
 | 
						|
        decoder = await TestLibExchangeRichErrorDecoderContract.deployFrom0xArtifactAsync(
 | 
						|
            artifacts.TestLibExchangeRichErrorDecoder,
 | 
						|
            provider,
 | 
						|
            txDefaults,
 | 
						|
            {},
 | 
						|
        );
 | 
						|
    });
 | 
						|
 | 
						|
    function createDecodeTest(revertType: new (...args: any[]) => RevertError, parameters: any[]): void {
 | 
						|
        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) => {
 | 
						|
            const wrapperFunctions = (decoder as any)[endpointName](_encoded);
 | 
						|
            return wrapperFunctions.callAsync.bind(wrapperFunctions).call((decoder as any)[endpointName]);
 | 
						|
        };
 | 
						|
        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 = randomAddress();
 | 
						|
        const validator = randomAddress();
 | 
						|
        const data = hexUtils.random(ERROR_DATA_LENGTH);
 | 
						|
        const signature = hexUtils.random(SIGNATURE_LENGTH);
 | 
						|
        const errorData = hexUtils.random(ERROR_DATA_LENGTH);
 | 
						|
        createDecodeTest(ExchangeRevertErrors.SignatureError, [errorCode, orderHash, signer, signature]);
 | 
						|
        createDecodeTest(ExchangeRevertErrors.SignatureValidatorNotApprovedError, [signer, validator]);
 | 
						|
        createDecodeTest(ExchangeRevertErrors.EIP1271SignatureError, [validator, data, signature, errorData]);
 | 
						|
        createDecodeTest(ExchangeRevertErrors.SignatureWalletError, [orderHash, signer, signature, errorData]);
 | 
						|
    })();
 | 
						|
 | 
						|
    (() => {
 | 
						|
        const orderHash = orderUtils.generatePseudoRandomOrderHash();
 | 
						|
        const orderStatus = OrderStatus.FullyFilled;
 | 
						|
        createDecodeTest(ExchangeRevertErrors.OrderStatusError, [orderHash, orderStatus]);
 | 
						|
    })();
 | 
						|
 | 
						|
    (() => {
 | 
						|
        const orderHash = orderUtils.generatePseudoRandomOrderHash();
 | 
						|
        const address = randomAddress();
 | 
						|
        createDecodeTest(ExchangeRevertErrors.ExchangeInvalidContextError, [
 | 
						|
            ExchangeRevertErrors.ExchangeContextErrorCodes.InvalidMaker,
 | 
						|
            orderHash,
 | 
						|
            address,
 | 
						|
        ]);
 | 
						|
        createDecodeTest(ExchangeRevertErrors.ExchangeInvalidContextError, [
 | 
						|
            ExchangeRevertErrors.ExchangeContextErrorCodes.InvalidTaker,
 | 
						|
            orderHash,
 | 
						|
            address,
 | 
						|
        ]);
 | 
						|
        createDecodeTest(ExchangeRevertErrors.ExchangeInvalidContextError, [
 | 
						|
            ExchangeRevertErrors.ExchangeContextErrorCodes.InvalidSender,
 | 
						|
            orderHash,
 | 
						|
            address,
 | 
						|
        ]);
 | 
						|
    })();
 | 
						|
 | 
						|
    (() => {
 | 
						|
        const errorCode = ExchangeRevertErrors.FillErrorCode.TakerOverpay;
 | 
						|
        const orderHash = orderUtils.generatePseudoRandomOrderHash();
 | 
						|
        createDecodeTest(ExchangeRevertErrors.FillError, [errorCode, orderHash]);
 | 
						|
    })();
 | 
						|
 | 
						|
    (() => {
 | 
						|
        const maker = randomAddress();
 | 
						|
        const sender = randomAddress();
 | 
						|
        const currentEpoch = generatePseudoRandomSalt();
 | 
						|
        createDecodeTest(ExchangeRevertErrors.OrderEpochError, [maker, sender, currentEpoch]);
 | 
						|
    })();
 | 
						|
 | 
						|
    (() => {
 | 
						|
        const assetProxyAddress = randomAddress();
 | 
						|
        createDecodeTest(ExchangeRevertErrors.AssetProxyExistsError, [
 | 
						|
            hexUtils.random(ASSET_PROXY_ID_LENGTH),
 | 
						|
            assetProxyAddress,
 | 
						|
        ]);
 | 
						|
    })();
 | 
						|
 | 
						|
    (() => {
 | 
						|
        const errorCode = ExchangeRevertErrors.AssetProxyDispatchErrorCode.UnknownAssetProxy;
 | 
						|
        const orderHash = orderUtils.generatePseudoRandomOrderHash();
 | 
						|
        const assetData = hexUtils.random(ASSET_DATA_LENGTH);
 | 
						|
        createDecodeTest(ExchangeRevertErrors.AssetProxyDispatchError, [errorCode, orderHash, assetData]);
 | 
						|
    })();
 | 
						|
 | 
						|
    (() => {
 | 
						|
        const orderHash = orderUtils.generatePseudoRandomOrderHash();
 | 
						|
        const assetData = hexUtils.random(ASSET_DATA_LENGTH);
 | 
						|
        const errorData = hexUtils.random(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 errorData = hexUtils.random(ERROR_DATA_LENGTH);
 | 
						|
        createDecodeTest(ExchangeRevertErrors.TransactionExecutionError, [transactionHash, errorData]);
 | 
						|
    })();
 | 
						|
 | 
						|
    (() => {
 | 
						|
        const errorCode = ExchangeRevertErrors.IncompleteFillErrorCode.IncompleteMarketSellOrders;
 | 
						|
        const expectedAmount = new BigNumber(hexUtils.random(WORD_LENGTH));
 | 
						|
        const actualAmount = new BigNumber(hexUtils.random(WORD_LENGTH));
 | 
						|
        createDecodeTest(ExchangeRevertErrors.IncompleteFillError, [errorCode, expectedAmount, actualAmount]);
 | 
						|
    })();
 | 
						|
});
 |