Add tooling and unit tests

This commit is contained in:
Michael Zhu 2020-03-03 17:11:26 -08:00
parent 2b1545145b
commit 5db065644c
3 changed files with 116 additions and 0 deletions

View File

@ -29,3 +29,4 @@ export {
TupleDataItem, TupleDataItem,
StateMutability, StateMutability,
} from 'ethereum-types'; } from 'ethereum-types';
export * from './max_gas_price_utils';

View File

@ -0,0 +1,44 @@
import { constants } from '@0x/contracts-test-utils';
import { assetDataUtils } from '@0x/order-utils';
import { StaticCallAssetData } from '@0x/types';
import { AbiEncoder, BigNumber } from '@0x/utils';
const maxGasPriceEncoder = AbiEncoder.create([{ name: 'maxGasPrice', type: 'uint256' }]);
const customGasPriceEncoder = AbiEncoder.createMethod('checkGasPrice', [{ name: 'data', type: 'bytes' }]);
const defaultGasPriceEncoder = AbiEncoder.createMethod('checkGasPrice', []);
const ONE_GWEI = new BigNumber(10 ** 9);
export const TWENTY_GWEI = ONE_GWEI.times(20);
/**
* Encodes the given stop limit data parameters into StaticCall asset data so that it can be used
* in a 0x order.
*/
export function encodeMaxGasPriceStaticCallData(maxGasPriceContractAddress: string, maxGasPrice?: BigNumber): string {
const staticCallData =
maxGasPrice === undefined
? defaultGasPriceEncoder.encode({})
: customGasPriceEncoder.encode({
data: maxGasPriceEncoder.encode({ maxGasPrice }),
});
return assetDataUtils.encodeStaticCallAssetData(
maxGasPriceContractAddress,
staticCallData,
constants.KECCAK256_NULL,
);
}
/**
* Decodes the maxGasPrice StaticCall asset data.
*/
export function decodeMaxGasPriceStaticCallData(assetData: string): BigNumber {
// tslint:disable-next-line:no-unnecessary-type-assertion
const { staticCallData } = assetDataUtils.decodeAssetDataOrThrow(assetData) as StaticCallAssetData;
try {
const { maxGasPrice } = maxGasPriceEncoder.decode(customGasPriceEncoder.strictDecode<string>(staticCallData));
return maxGasPrice;
} catch (e) {
defaultGasPriceEncoder.strictDecode(staticCallData);
return TWENTY_GWEI;
}
}

View File

@ -0,0 +1,71 @@
import { blockchainTests, constants, expect, getRandomInteger } from '@0x/contracts-test-utils';
import { AbiEncoder } from '@0x/utils';
import {
decodeMaxGasPriceStaticCallData,
encodeMaxGasPriceStaticCallData,
TWENTY_GWEI,
} from '../src/max_gas_price_utils';
import { artifacts } from './artifacts';
import { MaximumGasPriceContract } from './wrappers';
blockchainTests.resets('MaximumGasPrice unit tests', env => {
let maxGasPriceContract: MaximumGasPriceContract;
const maxGasPriceEncoder = AbiEncoder.create([{ name: 'maxGasPrice', type: 'uint256' }]);
before(async () => {
maxGasPriceContract = await MaximumGasPriceContract.deployFrom0xArtifactAsync(
artifacts.MaximumGasPrice,
env.provider,
env.txDefaults,
artifacts,
);
});
describe('Contract functionality', () => {
it('does not revert if tx.gasprice < default maximum', async () => {
await maxGasPriceContract.checkGasPrice1().callAsync({ gasPrice: TWENTY_GWEI.minus(1) });
});
it('does not revert if tx.gasprice = default maximum', async () => {
await maxGasPriceContract.checkGasPrice1().callAsync({ gasPrice: TWENTY_GWEI });
});
it('reverts if tx.gasPrice > default maximum', async () => {
const tx = maxGasPriceContract.checkGasPrice1().callAsync({ gasPrice: TWENTY_GWEI.plus(1) });
return expect(tx).to.revertWith('MaximumGasPrice/GAS_PRICE_EXCEEDS_20_GWEI');
});
it('does not revert if tx.gasprice < custom maximum', async () => {
const maxGasPrice = getRandomInteger(0, TWENTY_GWEI.times(2));
await maxGasPriceContract
.checkGasPrice2(maxGasPriceEncoder.encode({ maxGasPrice }))
.callAsync({ gasPrice: maxGasPrice.minus(1) });
});
it('does not revert if tx.gasprice = default maximum', async () => {
const maxGasPrice = getRandomInteger(0, TWENTY_GWEI.times(2));
await maxGasPriceContract
.checkGasPrice2(maxGasPriceEncoder.encode({ maxGasPrice }))
.callAsync({ gasPrice: maxGasPrice });
});
it('reverts if tx.gasPrice > default maximum', async () => {
const maxGasPrice = getRandomInteger(0, TWENTY_GWEI.times(2));
const tx = maxGasPriceContract
.checkGasPrice2(maxGasPriceEncoder.encode({ maxGasPrice }))
.callAsync({ gasPrice: maxGasPrice.plus(1) });
return expect(tx).to.revertWith('MaximumGasPrice/GAS_PRICE_EXCEEDS_MAXIMUM');
});
});
describe('Data encoding/decoding tools', () => {
it('correctly decodes default maximum gas price', async () => {
const encoded = encodeMaxGasPriceStaticCallData(maxGasPriceContract.address);
const decoded = decodeMaxGasPriceStaticCallData(encoded);
expect(decoded).to.bignumber.equal(TWENTY_GWEI);
});
it('correctly decodes custom maximum gas price', async () => {
const maxGasPrice = getRandomInteger(0, constants.MAX_UINT256);
const encoded = encodeMaxGasPriceStaticCallData(maxGasPriceContract.address, maxGasPrice);
const decoded = decodeMaxGasPriceStaticCallData(encoded);
expect(decoded).to.bignumber.equal(maxGasPrice);
});
});
});