diff options
author | Hsuan Lee <hsuan@cobinhood.com> | 2019-01-19 18:42:04 +0800 |
---|---|---|
committer | Hsuan Lee <hsuan@cobinhood.com> | 2019-01-19 18:42:04 +0800 |
commit | 7ae38906926dc09bc10670c361af0d2bf0050426 (patch) | |
tree | 5fb10ae366b987db09e4ddb4bc3ba0f75404ad08 /packages/utils | |
parent | b5fd3c72a08aaa6957917d74c333387a16edf66b (diff) | |
download | dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.gz dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.bz2 dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.lz dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.xz dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.tar.zst dexon-sol-tools-7ae38906926dc09bc10670c361af0d2bf0050426.zip |
Update dependency packages
Diffstat (limited to 'packages/utils')
63 files changed, 0 insertions, 6911 deletions
diff --git a/packages/utils/.npmignore b/packages/utils/.npmignore deleted file mode 100644 index 24e65ad5b..000000000 --- a/packages/utils/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -.* -yarn-error.log -/scripts/ -/src/ -tsconfig.json -/lib/monorepo_scripts/ diff --git a/packages/utils/CHANGELOG.json b/packages/utils/CHANGELOG.json deleted file mode 100644 index 0fb199e58..000000000 --- a/packages/utils/CHANGELOG.json +++ /dev/null @@ -1,423 +0,0 @@ -[ - { - "version": "4.0.0", - "changes": [ - { - "note": "Upgrade the bignumber.js to v8.0.2", - "pr": 1517 - } - ] - }, - { - "timestamp": 1547561734, - "version": "3.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "3.0.0", - "changes": [ - { - "note": "Make `promisify` resolve when the callback error is undefined.", - "pr": 1501 - } - ], - "timestamp": 1547225310 - }, - { - "version": "2.1.1", - "changes": [ - { - "note": "Add `should` prefix to names of properties in EncodingRules and DecodingRules", - "pr": 1363 - } - ], - "timestamp": 1547040760 - }, - { - "version": "2.1.0", - "changes": [ - { - "note": "Add `logWithTime` to `logUtils`", - "pr": 1461 - } - ] - }, - { - "version": "2.0.8", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1544739608 - }, - { - "version": "2.0.7", - "changes": [ - { - "note": "Optimized ABI Encoder/Decoder. Generates compressed calldata to save gas. Generates human-readable calldata to aid development." - } - ], - "timestamp": 1544570656 - }, - { - "timestamp": 1542821676, - "version": "2.0.6", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1542208198, - "version": "2.0.5", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "2.0.4", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1541740904 - }, - { - "timestamp": 1539871071, - "version": "2.0.3", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1538693146, - "version": "2.0.2", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1538475601, - "version": "2.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "2.0.0", - "changes": [ - { - "note": "Make abi_decoder compatible with ethers ^4.0.0", - "pr": 1069 - } - ], - "timestamp": 1538157789 - }, - { - "timestamp": 1537907159, - "version": "1.0.11", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1537875740, - "version": "1.0.10", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1537541580, - "version": "1.0.9", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1536142250, - "version": "1.0.8", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1535377027, - "version": "1.0.7", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1535133899, - "version": "1.0.6", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "1.0.5", - "changes": [ - { - "note": "Increased BigNumber decimal precision from 20 to 78", - "pr": 807 - }, - { - "note": "Store different ABIs for events with same function signature and different amount of indexed arguments", - "pr": 933 - } - ], - "timestamp": 1534210131 - }, - { - "timestamp": 1532619515, - "version": "1.0.4", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1532614997, - "version": "1.0.3", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1532605697, - "version": "1.0.2", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "1.0.1", - "changes": [ - { - "note": "Add `AbortController` polyfill to `fetchAsync`", - "pr": 903 - } - ], - "timestamp": 1532357734 - }, - { - "timestamp": 1532043000, - "version": "1.0.0", - "changes": [ - { - "note": "Add `fetchAsync` which adds a default timeout to all requests", - "pr": 874 - } - ] - }, - { - "timestamp": 1531919263, - "version": "0.7.3", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "0.7.2", - "changes": [ - { - "note": "Added errorUtils.spawnSwitchErr" - }, - { - "note": "Add logUtils.warn", - "pr": 589 - }, - { - "note": "Fixes uncaught Error in abi_decoder", - "pr": 763 - } - ], - "timestamp": 1531149657 - }, - { - "timestamp": 1529397769, - "version": "0.7.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "0.7.0", - "changes": [ - { - "note": "Incorrect publish that was unpublished" - } - ], - "timestamp": 1527810075 - }, - { - "timestamp": 1527009133, - "version": "0.6.2", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1525477860, - "version": "0.6.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "0.6.0", - "changes": [ - { - "note": "Update ethers-contracts to ethers.js", - "pr": 540 - } - ], - "timestamp": 1525428773 - }, - { - "version": "0.5.2", - "changes": [ - { - "note": "Export NULL_BYTES constant", - "pr": 500 - } - ], - "timestamp": 1524044013 - }, - { - "timestamp": 1523462196, - "version": "0.5.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "0.5.0", - "changes": [ - { - "note": "Make `AbiDecoder.addABI` public", - "pr": 485 - } - ], - "timestamp": 1522673609 - }, - { - "timestamp": 1522658513, - "version": "0.4.4", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "0.4.3", - "changes": [ - { - "note": "Add `@types/node` to dependencies since `intervalUtils` has the `NodeJS` type as part of its public interface." - } - ], - "timestamp": 1521298800 - }, - { - "version": "0.4.2", - "changes": [ - { - "note": "Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package", - "pr": 452 - } - ], - "timestamp": 1521298800 - }, - { - "version": "0.4.0", - "changes": [ - { - "note": "Use `ethers-contracts` as a backend to decode event args", - "pr": 413 - }, - { - "note": "Move web3 types from devDep to dep since required when using this package", - "pr": 429 - } - ], - "timestamp": 1520089200 - }, - { - "version": "0.3.2", - "changes": [ - { - "note": "Fix publishing issue where .npmignore was not properly excluding undesired content", - "pr": 389 - } - ], - "timestamp": 1518102000 - }, - { - "version": "0.3.0", - "changes": [ - { - "note": "Fix a bug related to event signature collisions (argument indexes aren't included in event signatures) in the abi_decoder. The decoder used to throw on unknown events with identical signatures as a known event (except indexes).", - "pr": 366 - } - ], - "timestamp": 1517756400 - }, - { - "version": "0.2.0", - "changes": [ - { - "note": "Add `onError` parameter to `intervalUtils.setAsyncExcludingInterval`", - "pr": 312 - }, - { - "note": "Add `intervalUtils.setInterval`", - "pr": 312 - } - ], - "timestamp": 1516114800 - } -] diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md deleted file mode 100644 index ed3f00158..000000000 --- a/packages/utils/CHANGELOG.md +++ /dev/null @@ -1,179 +0,0 @@ -<!-- -changelogUtils.file is auto-generated using the monorepo-scripts package. Don't edit directly. -Edit the package's CHANGELOG.json file only. ---> - -CHANGELOG - -## v3.0.1 - _January 15, 2019_ - - * Dependencies updated - -## v3.0.0 - _January 11, 2019_ - - * Make `promisify` resolve when the callback error is undefined. (#1501) - -## v2.1.1 - _January 9, 2019_ - - * Add `should` prefix to names of properties in EncodingRules and DecodingRules (#1363) - -## v2.1.0 - _Invalid date_ - - * Add `logWithTime` to `logUtils` (#1461) - -## v2.0.8 - _December 13, 2018_ - - * Dependencies updated - -## v2.0.7 - _December 11, 2018_ - - * Optimized ABI Encoder/Decoder. Generates compressed calldata to save gas. Generates human-readable calldata to aid development. - -## v2.0.6 - _November 21, 2018_ - - * Dependencies updated - -## v2.0.5 - _November 14, 2018_ - - * Dependencies updated - -## v2.0.4 - _November 9, 2018_ - - * Dependencies updated - -## v2.0.3 - _October 18, 2018_ - - * Dependencies updated - -## v2.0.2 - _October 4, 2018_ - - * Dependencies updated - -## v2.0.1 - _October 2, 2018_ - - * Dependencies updated - -## v2.0.0 - _September 28, 2018_ - - * Make abi_decoder compatible with ethers ^4.0.0 (#1069) - -## v1.0.11 - _September 25, 2018_ - - * Dependencies updated - -## v1.0.10 - _September 25, 2018_ - - * Dependencies updated - -## v1.0.9 - _September 21, 2018_ - - * Dependencies updated - -## v1.0.8 - _September 5, 2018_ - - * Dependencies updated - -## v1.0.7 - _August 27, 2018_ - - * Dependencies updated - -## v1.0.6 - _August 24, 2018_ - - * Dependencies updated - -## v1.0.5 - _August 14, 2018_ - - * Increased BigNumber decimal precision from 20 to 78 (#807) - * Store different ABIs for events with same function signature and different amount of indexed arguments (#933) - -## v1.0.4 - _July 26, 2018_ - - * Dependencies updated - -## v1.0.3 - _July 26, 2018_ - - * Dependencies updated - -## v1.0.2 - _July 26, 2018_ - - * Dependencies updated - -## v1.0.1 - _July 23, 2018_ - - * Add `AbortController` polyfill to `fetchAsync` (#903) - -## v1.0.0 - _July 19, 2018_ - - * Add `fetchAsync` which adds a default timeout to all requests (#874) - -## v0.7.3 - _July 18, 2018_ - - * Dependencies updated - -## v0.7.2 - _July 9, 2018_ - - * Added errorUtils.spawnSwitchErr - * Add logUtils.warn (#589) - * Fixes uncaught Error in abi_decoder (#763) - -## v0.7.1 - _June 19, 2018_ - - * Dependencies updated - -## v0.7.0 - _May 31, 2018_ - - * Incorrect publish that was unpublished - -## v0.6.2 - _May 22, 2018_ - - * Dependencies updated - -## v0.6.1 - _May 4, 2018_ - - * Dependencies updated - -## v0.6.0 - _May 4, 2018_ - - * Update ethers-contracts to ethers.js (#540) - -## v0.5.2 - _April 18, 2018_ - - * Export NULL_BYTES constant (#500) - -## v0.5.1 - _April 11, 2018_ - - * Dependencies updated - -## v0.5.0 - _April 2, 2018_ - - * Make `AbiDecoder.addABI` public (#485) - -## v0.4.4 - _April 2, 2018_ - - * Dependencies updated - -## v0.4.3 - _March 17, 2018_ - - * Add `@types/node` to dependencies since `intervalUtils` has the `NodeJS` type as part of its public interface. - -## v0.4.2 - _March 17, 2018_ - - * Consolidate all `console.log` calls into `logUtils` in the `@0xproject/utils` package (#452) - -## v0.4.0 - _March 3, 2018_ - - * Use `ethers-contracts` as a backend to decode event args (#413) - * Move web3 types from devDep to dep since required when using this package (#429) - -## v0.3.2 - _February 8, 2018_ - - * Fix publishing issue where .npmignore was not properly excluding undesired content (#389) - -## v0.3.0 - _February 4, 2018_ - - * Fix a bug related to event signature collisions (argument indexes aren't included in event signatures) in the abi_decoder. The decoder used to throw on unknown events with identical signatures as a known event (except indexes). (#366) - -## v0.2.0 - _January 16, 2018_ - - * Add `onError` parameter to `intervalUtils.setAsyncExcludingInterval` (#312) - * Add `intervalUtils.setInterval` (#312) diff --git a/packages/utils/README.md b/packages/utils/README.md deleted file mode 100644 index 0b15f00c5..000000000 --- a/packages/utils/README.md +++ /dev/null @@ -1,84 +0,0 @@ -## @0x/utils - -Utils to be shared across 0x projects and packages - -## Installation - -```bash -yarn add @0x/utils -``` - -If your project is in [TypeScript](https://www.typescriptlang.org/), add the following to your `tsconfig.json`: - -```json -"compilerOptions": { - "typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"], -} -``` - -## Usage - -```javascript -import { addressUtils, bigNumberConfigs, classUtils, intervalUtils, promisify } from '@0x/utils'; -``` - -## Troubleshooting - -If you are still seeing TS type errors complaining about missing DOM types such as `Response`: - -``` -error TS2304: Cannot find name 'Response'. -``` - -Then you need to explicitly add the `dom` lib to your compiler options in `tsconfig.json`. The `dom` library is included by default, but customizing the `lib` option can cause it to be dropped. - -``` -"compilerOptions": { - "lib": [..., "dom"], -``` - -## Contributing - -We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository. - -Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. - -### Install dependencies - -If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: - -```bash -yarn config set workspaces-experimental true -``` - -Then install dependencies - -```bash -yarn install -``` - -### Build - -To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory: - -```bash -PKG=@0x/utils yarn build -``` - -Or continuously rebuild on change: - -```bash -PKG=@0x/utils yarn watch -``` - -### Clean - -```bash -yarn clean -``` - -### Lint - -```bash -yarn lint -``` diff --git a/packages/utils/coverage/.gitkeep b/packages/utils/coverage/.gitkeep deleted file mode 100644 index e69de29bb..000000000 --- a/packages/utils/coverage/.gitkeep +++ /dev/null diff --git a/packages/utils/package.json b/packages/utils/package.json deleted file mode 100644 index b6be39210..000000000 --- a/packages/utils/package.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "@0x/utils", - "version": "3.0.1", - "engines": { - "node": ">=6.12" - }, - "description": "0x TS utils", - "main": "lib/src/index.js", - "types": "lib/src/index.d.ts", - "scripts": { - "build": "tsc -b", - "build:ci": "yarn build", - "clean": "shx rm -rf lib", - "lint": "tslint --format stylish --project .", - "test": "yarn run_mocha", - "test:circleci": "yarn test:coverage", - "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js --bail --exit", - "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", - "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info" - }, - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/0xProject/0x-monorepo.git" - }, - "bugs": { - "url": "https://github.com/0xProject/0x-monorepo/issues" - }, - "homepage": "https://github.com/0xProject/0x-monorepo/packages/utils/README.md", - "devDependencies": { - "@0x/tslint-config": "^2.0.2", - "@types/detect-node": "2.0.0", - "@types/lodash": "4.14.104", - "@types/mocha": "^2.2.42", - "chai": "^4.0.1", - "chai-as-promised": "^7.1.0", - "chai-bignumber": "^3.0.0", - "dirty-chai": "^2.0.1", - "make-promises-safe": "^1.1.0", - "mocha": "^4.1.0", - "npm-run-all": "^4.1.2", - "shx": "^0.2.2", - "tslint": "5.11.0", - "typescript": "3.0.1" - }, - "dependencies": { - "@0x/types": "^1.5.2", - "@0x/typescript-typings": "^3.0.8", - "@types/node": "*", - "abortcontroller-polyfill": "^1.1.9", - "bignumber.js": "~8.0.2", - "chalk": "^2.4.1", - "detect-node": "2.0.3", - "ethereum-types": "^1.1.6", - "ethereumjs-util": "^5.1.1", - "ethers": "~4.0.4", - "isomorphic-fetch": "^2.2.1", - "js-sha3": "^0.7.0", - "lodash": "^4.17.5" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/utils/src/abi_decoder.ts b/packages/utils/src/abi_decoder.ts deleted file mode 100644 index 28b6418d8..000000000 --- a/packages/utils/src/abi_decoder.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { - AbiDefinition, - AbiType, - DecodedLogArgs, - EventAbi, - EventParameter, - LogEntry, - LogWithDecodedArgs, - RawLog, - SolidityTypes, -} from 'ethereum-types'; -import * as ethers from 'ethers'; -import * as _ from 'lodash'; - -import { addressUtils } from './address_utils'; -import { BigNumber } from './configured_bignumber'; - -/** - * AbiDecoder allows you to decode event logs given a set of supplied contract ABI's. It takes the contract's event - * signature from the ABI and attempts to decode the logs using it. - */ -export class AbiDecoder { - private readonly _methodIds: { [signatureHash: string]: { [numIndexedArgs: number]: EventAbi } } = {}; - /** - * Instantiate an AbiDecoder - * @param abiArrays An array of contract ABI's - * @return AbiDecoder instance - */ - constructor(abiArrays: AbiDefinition[][]) { - _.forEach(abiArrays, this.addABI.bind(this)); - } - /** - * Attempt to decode a log given the ABI's the AbiDecoder knows about. - * @param log The log to attempt to decode - * @return The decoded log if the requisite ABI was available. Otherwise the log unaltered. - */ - public tryToDecodeLogOrNoop<ArgsType extends DecodedLogArgs>(log: LogEntry): LogWithDecodedArgs<ArgsType> | RawLog { - const methodId = log.topics[0]; - const numIndexedArgs = log.topics.length - 1; - if (_.isUndefined(this._methodIds[methodId]) || _.isUndefined(this._methodIds[methodId][numIndexedArgs])) { - return log; - } - const event = this._methodIds[methodId][numIndexedArgs]; - const ethersInterface = new ethers.utils.Interface([event]); - const decodedParams: DecodedLogArgs = {}; - let topicsIndex = 1; - - let decodedData: any[]; - try { - decodedData = ethersInterface.events[event.name].decode(log.data); - } catch (error) { - if (error.code === ethers.errors.INVALID_ARGUMENT) { - // Because we index events by Method ID, and Method IDs are derived from the method - // name and the input parameters, it's possible that the return value of the event - // does not match our ABI. If that's the case, then ethers will throw an error - // when we try to parse the event. We handle that case here by returning the log rather - // than throwing an error. - return log; - } - throw error; - } - let didFailToDecode = false; - _.forEach(event.inputs, (param: EventParameter, i: number) => { - // Indexed parameters are stored in topics. Non-indexed ones in decodedData - let value: BigNumber | string | number = param.indexed ? log.topics[topicsIndex++] : decodedData[i]; - if (_.isUndefined(value)) { - didFailToDecode = true; - return; - } - if (param.type === SolidityTypes.Address) { - const baseHex = 16; - value = addressUtils.padZeros(new BigNumber((value as string).toLowerCase()).toString(baseHex)); - } else if (param.type === SolidityTypes.Uint256 || param.type === SolidityTypes.Uint) { - value = new BigNumber(value); - } else if (param.type === SolidityTypes.Uint8) { - value = new BigNumber(value).toNumber(); - } - decodedParams[param.name] = value; - }); - - if (didFailToDecode) { - return log; - } else { - return { - ...log, - event: event.name, - args: decodedParams, - }; - } - } - /** - * Add additional ABI definitions to the AbiDecoder - * @param abiArray An array of ABI definitions to add to the AbiDecoder - */ - public addABI(abiArray: AbiDefinition[]): void { - if (_.isUndefined(abiArray)) { - return; - } - const ethersInterface = new ethers.utils.Interface(abiArray); - _.map(abiArray, (abi: AbiDefinition) => { - if (abi.type === AbiType.Event) { - // tslint:disable-next-line:no-unnecessary-type-assertion - const eventAbi = abi as EventAbi; - const topic = ethersInterface.events[eventAbi.name].topic; - const numIndexedArgs = _.reduce(eventAbi.inputs, (sum, input) => (input.indexed ? sum + 1 : sum), 0); - this._methodIds[topic] = { - ...this._methodIds[topic], - [numIndexedArgs]: eventAbi, - }; - } - }); - } -} diff --git a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts b/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts deleted file mode 100644 index f23324721..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/data_type.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { Calldata } from '../calldata/calldata'; -import { CalldataBlock } from '../calldata/calldata_block'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; -import { DecodingRules, EncodingRules } from '../utils/rules'; - -import { DataTypeFactory } from './interfaces'; - -export abstract class DataType { - private readonly _dataItem: DataItem; - private readonly _factory: DataTypeFactory; - - constructor(dataItem: DataItem, factory: DataTypeFactory) { - this._dataItem = dataItem; - this._factory = factory; - } - - public getDataItem(): DataItem { - return this._dataItem; - } - - public getFactory(): DataTypeFactory { - return this._factory; - } - - public encode(value: any, rules?: EncodingRules, selector?: string): string { - const rules_ = _.isUndefined(rules) ? constants.DEFAULT_ENCODING_RULES : rules; - const calldata = new Calldata(rules_); - if (!_.isUndefined(selector)) { - calldata.setSelector(selector); - } - const block = this.generateCalldataBlock(value); - calldata.setRoot(block); - const encodedCalldata = calldata.toString(); - return encodedCalldata; - } - - public decode(calldata: string, rules?: DecodingRules, selector?: string): any { - if (!_.isUndefined(selector) && !_.startsWith(calldata, selector)) { - throw new Error( - `Tried to decode calldata, but it was missing the function selector. Expected prefix '${selector}'. Got '${calldata}'.`, - ); - } - const hasSelector = !_.isUndefined(selector); - const rawCalldata = new RawCalldata(calldata, hasSelector); - const rules_ = _.isUndefined(rules) ? constants.DEFAULT_DECODING_RULES : rules; - const value = this.generateValue(rawCalldata, rules_); - return value; - } - - public decodeAsArray(returndata: string, rules?: DecodingRules): any[] { - const value = this.decode(returndata, rules); - const valuesAsArray = _.isObject(value) ? _.values(value) : [value]; - return valuesAsArray; - } - - public getSignature(isDetailed?: boolean): string { - if (_.isEmpty(this._dataItem.name) || !isDetailed) { - return this.getSignatureType(); - } - const name = this.getDataItem().name; - const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); - const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; - const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 1) : name; - const detailedSignature = `${shortName} ${this.getSignatureType()}`; - return detailedSignature; - } - - public abstract generateCalldataBlock(value: any, parentBlock?: CalldataBlock): CalldataBlock; - public abstract generateValue(calldata: RawCalldata, rules: DecodingRules): any; - public abstract getSignatureType(): string; - public abstract isStatic(): boolean; -} diff --git a/packages/utils/src/abi_encoder/abstract_data_types/interfaces.ts b/packages/utils/src/abi_encoder/abstract_data_types/interfaces.ts deleted file mode 100644 index 2f2f60871..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/interfaces.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { DataItem } from 'ethereum-types'; - -import { RawCalldata } from '../calldata/raw_calldata'; - -import { DataType } from './data_type'; - -export interface DataTypeFactory { - create: (dataItem: DataItem, parentDataType?: DataType) => DataType; -} - -export interface DataTypeStaticInterface { - matchType: (type: string) => boolean; - encodeValue: (value: any) => Buffer; - decodeValue: (rawCalldata: RawCalldata) => any; -} - -export interface MemberIndexByName { - [key: string]: number; -} diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts deleted file mode 100644 index a091e55b9..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/blob.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { BlobCalldataBlock } from '../../calldata/blocks/blob'; -import { CalldataBlock } from '../../calldata/calldata_block'; -import { RawCalldata } from '../../calldata/raw_calldata'; -import { DecodingRules } from '../../utils/rules'; - -import { DataType } from '../data_type'; -import { DataTypeFactory } from '../interfaces'; - -export abstract class AbstractBlobDataType extends DataType { - protected _sizeKnownAtCompileTime: boolean; - - public constructor(dataItem: DataItem, factory: DataTypeFactory, sizeKnownAtCompileTime: boolean) { - super(dataItem, factory); - this._sizeKnownAtCompileTime = sizeKnownAtCompileTime; - } - - public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): BlobCalldataBlock { - const encodedValue = this.encodeValue(value); - const name = this.getDataItem().name; - const signature = this.getSignature(); - const parentName = _.isUndefined(parentBlock) ? '' : parentBlock.getName(); - const block = new BlobCalldataBlock(name, signature, parentName, encodedValue); - return block; - } - - public generateValue(calldata: RawCalldata, rules: DecodingRules): any { - const value = this.decodeValue(calldata); - return value; - } - - public isStatic(): boolean { - return this._sizeKnownAtCompileTime; - } - - public abstract encodeValue(value: any): Buffer; - public abstract decodeValue(calldata: RawCalldata): any; -} diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/pointer.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/pointer.ts deleted file mode 100644 index 0f3c55280..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/pointer.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { PointerCalldataBlock } from '../../calldata/blocks/pointer'; -import { CalldataBlock } from '../../calldata/calldata_block'; -import { RawCalldata } from '../../calldata/raw_calldata'; -import { constants } from '../../utils/constants'; -import { DecodingRules } from '../../utils/rules'; - -import { DataType } from '../data_type'; -import { DataTypeFactory } from '../interfaces'; - -export abstract class AbstractPointerDataType extends DataType { - protected _destination: DataType; - protected _parent: DataType; - - public constructor(dataItem: DataItem, factory: DataTypeFactory, destination: DataType, parent: DataType) { - super(dataItem, factory); - this._destination = destination; - this._parent = parent; - } - - public generateCalldataBlock(value: any, parentBlock?: CalldataBlock): PointerCalldataBlock { - if (_.isUndefined(parentBlock)) { - throw new Error(`DependentDataType requires a parent block to generate its block`); - } - const destinationBlock = this._destination.generateCalldataBlock(value, parentBlock); - const name = this.getDataItem().name; - const signature = this.getSignature(); - const parentName = parentBlock.getName(); - const block = new PointerCalldataBlock(name, signature, parentName, destinationBlock, parentBlock); - return block; - } - - public generateValue(calldata: RawCalldata, rules: DecodingRules): any { - const destinationOffsetBuf = calldata.popWord(); - const destinationOffsetHex = ethUtil.bufferToHex(destinationOffsetBuf); - const destinationOffsetRelative = parseInt(destinationOffsetHex, constants.HEX_BASE); - const destinationOffsetAbsolute = calldata.toAbsoluteOffset(destinationOffsetRelative); - const currentOffset = calldata.getOffset(); - calldata.setOffset(destinationOffsetAbsolute); - const value = this._destination.generateValue(calldata, rules); - calldata.setOffset(currentOffset); - return value; - } - - // Disable prefer-function-over-method for inherited abstract method. - /* tslint:disable prefer-function-over-method */ - public isStatic(): boolean { - return true; - } - /* tslint:enable prefer-function-over-method */ -} diff --git a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts b/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts deleted file mode 100644 index 2c6c4b0f6..000000000 --- a/packages/utils/src/abi_encoder/abstract_data_types/types/set.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { ObjectMap } from '@0x/types'; -import { DataItem } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { BigNumber } from '../../../configured_bignumber'; -import { SetCalldataBlock } from '../../calldata/blocks/set'; -import { CalldataBlock } from '../../calldata/calldata_block'; -import { RawCalldata } from '../../calldata/raw_calldata'; -import { constants } from '../../utils/constants'; -import { DecodingRules } from '../../utils/rules'; - -import { DataType } from '../data_type'; -import { DataTypeFactory, MemberIndexByName } from '../interfaces'; - -import { AbstractPointerDataType } from './pointer'; - -export abstract class AbstractSetDataType extends DataType { - protected readonly _arrayLength: number | undefined; - protected readonly _arrayElementType: string | undefined; - private readonly _memberIndexByName: MemberIndexByName; - private readonly _members: DataType[]; - private readonly _isArray: boolean; - - public constructor( - dataItem: DataItem, - factory: DataTypeFactory, - isArray: boolean = false, - arrayLength?: number, - arrayElementType?: string, - ) { - super(dataItem, factory); - this._memberIndexByName = {}; - this._members = []; - this._isArray = isArray; - this._arrayLength = arrayLength; - this._arrayElementType = arrayElementType; - if (isArray && !_.isUndefined(arrayLength)) { - [this._members, this._memberIndexByName] = this._createMembersWithLength(dataItem, arrayLength); - } else if (!isArray) { - [this._members, this._memberIndexByName] = this._createMembersWithKeys(dataItem); - } - } - - public generateCalldataBlock(value: any[] | object, parentBlock?: CalldataBlock): SetCalldataBlock { - const block = - value instanceof Array - ? this._generateCalldataBlockFromArray(value, parentBlock) - : this._generateCalldataBlockFromObject(value, parentBlock); - return block; - } - - public generateValue(calldata: RawCalldata, rules: DecodingRules): any[] | object { - let members = this._members; - // Case 1: This is an array of undefined length, which means that `this._members` was not - // populated in the constructor. So we must construct the set of members now. - if (this._isArray && _.isUndefined(this._arrayLength)) { - const arrayLengthBuf = calldata.popWord(); - const arrayLengthHex = ethUtil.bufferToHex(arrayLengthBuf); - const arrayLength = new BigNumber(arrayLengthHex, constants.HEX_BASE); - [members] = this._createMembersWithLength(this.getDataItem(), arrayLength.toNumber()); - } - // Create a new scope in the calldata, before descending into the members of this set. - calldata.startScope(); - let value: any[] | object; - if (rules.shouldConvertStructsToObjects && !this._isArray) { - // Construct an object with values for each member of the set. - value = {}; - _.each(this._memberIndexByName, (idx: number, key: string) => { - const member = this._members[idx]; - const memberValue = member.generateValue(calldata, rules); - (value as { [key: string]: any })[key] = memberValue; - }); - } else { - // Construct an array with values for each member of the set. - value = []; - _.each(members, (member: DataType, idx: number) => { - const memberValue = member.generateValue(calldata, rules); - (value as any[]).push(memberValue); - }); - } - // Close this scope and return tetheh value. - calldata.endScope(); - return value; - } - - public isStatic(): boolean { - // An array with an undefined length is never static. - if (this._isArray && _.isUndefined(this._arrayLength)) { - return false; - } - // If any member of the set is a pointer then the set is not static. - const dependentMember = _.find(this._members, (member: DataType) => { - return member instanceof AbstractPointerDataType; - }); - const isStatic = _.isUndefined(dependentMember); - return isStatic; - } - - protected _generateCalldataBlockFromArray(value: any[], parentBlock?: CalldataBlock): SetCalldataBlock { - // Sanity check: if the set has a defined length then `value` must have the same length. - if (!_.isUndefined(this._arrayLength) && value.length !== this._arrayLength) { - throw new Error( - `Expected array of ${JSON.stringify( - this._arrayLength, - )} elements, but got array of length ${JSON.stringify(value.length)}`, - ); - } - // Create a new calldata block for this set. - const parentName = _.isUndefined(parentBlock) ? '' : parentBlock.getName(); - const block = new SetCalldataBlock(this.getDataItem().name, this.getSignature(), parentName); - // If this set has an undefined length then set its header to be the number of elements. - let members = this._members; - if (this._isArray && _.isUndefined(this._arrayLength)) { - [members] = this._createMembersWithLength(this.getDataItem(), value.length); - const lenBuf = ethUtil.setLengthLeft( - ethUtil.toBuffer(`0x${value.length.toString(constants.HEX_BASE)}`), - constants.EVM_WORD_WIDTH_IN_BYTES, - ); - block.setHeader(lenBuf); - } - // Create blocks for members of set. - const memberCalldataBlocks: CalldataBlock[] = []; - _.each(members, (member: DataType, idx: number) => { - const memberBlock = member.generateCalldataBlock(value[idx], block); - memberCalldataBlocks.push(memberBlock); - }); - block.setMembers(memberCalldataBlocks); - return block; - } - - protected _generateCalldataBlockFromObject(obj: object, parentBlock?: CalldataBlock): SetCalldataBlock { - // Create a new calldata block for this set. - const parentName = _.isUndefined(parentBlock) ? '' : parentBlock.getName(); - const block = new SetCalldataBlock(this.getDataItem().name, this.getSignature(), parentName); - // Create blocks for members of set. - const memberCalldataBlocks: CalldataBlock[] = []; - _.forEach(this._memberIndexByName, (memberIndex: number, memberName: string) => { - if (!(memberName in obj)) { - throw new Error( - `Could not assign tuple to object: missing key '${memberName}' in object ${JSON.stringify(obj)}`, - ); - } - const memberValue: any = (obj as ObjectMap<any>)[memberName]; - const memberBlock = this._members[memberIndex].generateCalldataBlock(memberValue, block); - memberCalldataBlocks.push(memberBlock); - }); - // Associate member blocks with Set block. - block.setMembers(memberCalldataBlocks); - return block; - } - - protected _computeSignatureOfMembers(isDetailed?: boolean): string { - // Compute signature of members - let signature = `(`; - _.each(this._members, (member: DataType, i: number) => { - signature += member.getSignature(isDetailed); - if (i < this._members.length - 1) { - signature += ','; - } - }); - signature += ')'; - return signature; - } - - private _createMembersWithKeys(dataItem: DataItem): [DataType[], MemberIndexByName] { - // Sanity check - if (_.isUndefined(dataItem.components)) { - throw new Error( - `Tried to create a set using key/value pairs, but no components were defined by the input DataItem '${ - dataItem.name - }'.`, - ); - } - // Create one member for each component of `dataItem` - const members: DataType[] = []; - const memberIndexByName: MemberIndexByName = {}; - const memberNames: string[] = []; - _.each(dataItem.components, (memberItem: DataItem) => { - // If a component with `name` already exists then - // rename to `name_nameIdx` to avoid naming conflicts. - let memberName = memberItem.name; - let nameIdx = 0; - while (_.includes(memberNames, memberName) || _.isEmpty(memberName)) { - nameIdx++; - memberName = `${memberItem.name}_${nameIdx}`; - } - memberNames.push(memberName); - const childDataItem: DataItem = { - type: memberItem.type, - name: `${dataItem.name}.${memberName}`, - }; - const components = memberItem.components; - if (!_.isUndefined(components)) { - childDataItem.components = components; - } - const child = this.getFactory().create(childDataItem, this); - memberIndexByName[memberName] = members.length; - members.push(child); - }); - return [members, memberIndexByName]; - } - - private _createMembersWithLength(dataItem: DataItem, length: number): [DataType[], MemberIndexByName] { - // Create `length` members, deriving the type from `dataItem` - const members: DataType[] = []; - const memberIndexByName: MemberIndexByName = {}; - const range = _.range(length); - _.each(range, (idx: number) => { - const memberDataItem: DataItem = { - type: _.isUndefined(this._arrayElementType) ? '' : this._arrayElementType, - name: `${dataItem.name}[${idx.toString(constants.DEC_BASE)}]`, - }; - const components = dataItem.components; - if (!_.isUndefined(components)) { - memberDataItem.components = components; - } - const memberType = this.getFactory().create(memberDataItem, this); - memberIndexByName[idx.toString(constants.DEC_BASE)] = members.length; - members.push(memberType); - }); - return [members, memberIndexByName]; - } -} diff --git a/packages/utils/src/abi_encoder/calldata/blocks/blob.ts b/packages/utils/src/abi_encoder/calldata/blocks/blob.ts deleted file mode 100644 index 219ea6c61..000000000 --- a/packages/utils/src/abi_encoder/calldata/blocks/blob.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { CalldataBlock } from '../calldata_block'; - -export class BlobCalldataBlock extends CalldataBlock { - private readonly _blob: Buffer; - - constructor(name: string, signature: string, parentName: string, blob: Buffer) { - const headerSizeInBytes = 0; - const bodySizeInBytes = blob.byteLength; - super(name, signature, parentName, headerSizeInBytes, bodySizeInBytes); - this._blob = blob; - } - - public toBuffer(): Buffer { - return this._blob; - } - - public getRawData(): Buffer { - return this._blob; - } -} diff --git a/packages/utils/src/abi_encoder/calldata/blocks/pointer.ts b/packages/utils/src/abi_encoder/calldata/blocks/pointer.ts deleted file mode 100644 index 72d6a3173..000000000 --- a/packages/utils/src/abi_encoder/calldata/blocks/pointer.ts +++ /dev/null @@ -1,61 +0,0 @@ -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { constants } from '../../utils/constants'; - -import { CalldataBlock } from '../calldata_block'; - -export class PointerCalldataBlock extends CalldataBlock { - public static readonly RAW_DATA_START = new Buffer('<'); - public static readonly RAW_DATA_END = new Buffer('>'); - private static readonly _DEPENDENT_PAYLOAD_SIZE_IN_BYTES = 32; - private static readonly _EMPTY_HEADER_SIZE = 0; - private readonly _parent: CalldataBlock; - private readonly _dependency: CalldataBlock; - private _aliasFor: CalldataBlock | undefined; - - constructor(name: string, signature: string, parentName: string, dependency: CalldataBlock, parent: CalldataBlock) { - const headerSizeInBytes = PointerCalldataBlock._EMPTY_HEADER_SIZE; - const bodySizeInBytes = PointerCalldataBlock._DEPENDENT_PAYLOAD_SIZE_IN_BYTES; - super(name, signature, parentName, headerSizeInBytes, bodySizeInBytes); - this._parent = parent; - this._dependency = dependency; - this._aliasFor = undefined; - } - - public toBuffer(): Buffer { - const destinationOffset = !_.isUndefined(this._aliasFor) - ? this._aliasFor.getOffsetInBytes() - : this._dependency.getOffsetInBytes(); - const parentOffset = this._parent.getOffsetInBytes(); - const parentHeaderSize = this._parent.getHeaderSizeInBytes(); - const pointer: number = destinationOffset - (parentOffset + parentHeaderSize); - const pointerHex = `0x${pointer.toString(constants.HEX_BASE)}`; - const pointerBuf = ethUtil.toBuffer(pointerHex); - const pointerBufPadded = ethUtil.setLengthLeft(pointerBuf, constants.EVM_WORD_WIDTH_IN_BYTES); - return pointerBufPadded; - } - - public getDependency(): CalldataBlock { - return this._dependency; - } - - public setAlias(block: CalldataBlock): void { - this._aliasFor = block; - this._setName(`${this.getName()} (alias for ${block.getName()})`); - } - - public getAlias(): CalldataBlock | undefined { - return this._aliasFor; - } - - public getRawData(): Buffer { - const dependencyRawData = this._dependency.getRawData(); - const rawDataComponents: Buffer[] = []; - rawDataComponents.push(PointerCalldataBlock.RAW_DATA_START); - rawDataComponents.push(dependencyRawData); - rawDataComponents.push(PointerCalldataBlock.RAW_DATA_END); - const rawData = Buffer.concat(rawDataComponents); - return rawData; - } -} diff --git a/packages/utils/src/abi_encoder/calldata/blocks/set.ts b/packages/utils/src/abi_encoder/calldata/blocks/set.ts deleted file mode 100644 index d1abc4986..000000000 --- a/packages/utils/src/abi_encoder/calldata/blocks/set.ts +++ /dev/null @@ -1,47 +0,0 @@ -import * as _ from 'lodash'; - -import { CalldataBlock } from '../calldata_block'; - -export class SetCalldataBlock extends CalldataBlock { - private _header: Buffer | undefined; - private _members: CalldataBlock[]; - - constructor(name: string, signature: string, parentName: string) { - super(name, signature, parentName, 0, 0); - this._members = []; - this._header = undefined; - } - - public getRawData(): Buffer { - const rawDataComponents: Buffer[] = []; - if (!_.isUndefined(this._header)) { - rawDataComponents.push(this._header); - } - _.each(this._members, (member: CalldataBlock) => { - const memberBuffer = member.getRawData(); - rawDataComponents.push(memberBuffer); - }); - const rawData = Buffer.concat(rawDataComponents); - return rawData; - } - - public setMembers(members: CalldataBlock[]): void { - this._members = members; - } - - public setHeader(header: Buffer): void { - this._setHeaderSize(header.byteLength); - this._header = header; - } - - public toBuffer(): Buffer { - if (!_.isUndefined(this._header)) { - return this._header; - } - return new Buffer(''); - } - - public getMembers(): CalldataBlock[] { - return this._members; - } -} diff --git a/packages/utils/src/abi_encoder/calldata/calldata.ts b/packages/utils/src/abi_encoder/calldata/calldata.ts deleted file mode 100644 index b08fb71ce..000000000 --- a/packages/utils/src/abi_encoder/calldata/calldata.ts +++ /dev/null @@ -1,245 +0,0 @@ -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { constants } from '../utils/constants'; -import { EncodingRules } from '../utils/rules'; - -import { PointerCalldataBlock } from './blocks/pointer'; -import { SetCalldataBlock } from './blocks/set'; -import { CalldataBlock } from './calldata_block'; -import { CalldataIterator, ReverseCalldataIterator } from './iterator'; - -export class Calldata { - private readonly _rules: EncodingRules; - private _selector: string; - private _root: CalldataBlock | undefined; - - public constructor(rules: EncodingRules) { - this._rules = rules; - this._selector = ''; - this._root = undefined; - } - /** - * Sets the root calldata block. This block usually corresponds to a Method. - */ - public setRoot(block: CalldataBlock): void { - this._root = block; - } - /** - * Sets the selector to be prepended onto the calldata. - * If the root block was created by a Method then a selector will likely be set. - */ - public setSelector(selector: string): void { - if (!_.startsWith(selector, '0x')) { - throw new Error(`Expected selector to be hex. Missing prefix '0x'`); - } else if (selector.length !== constants.HEX_SELECTOR_LENGTH_IN_CHARS) { - throw new Error(`Invalid selector '${selector}'`); - } - this._selector = selector; - } - /** - * Iterates through the calldata blocks, starting from the root block, to construct calldata as a hex string. - * If the `optimize` flag is set then this calldata will be condensed, to save gas. - * If the `annotate` flag is set then this will return human-readable calldata. - * If the `annotate` flag is *not* set then this will return EVM-compatible calldata. - */ - public toString(): string { - // Sanity check: root block must be set - if (_.isUndefined(this._root)) { - throw new Error('expected root'); - } - // Optimize, if flag set - if (this._rules.shouldOptimize) { - this._optimize(); - } - // Set offsets - const iterator = new CalldataIterator(this._root); - let offset = 0; - for (const block of iterator) { - block.setOffset(offset); - offset += block.getSizeInBytes(); - } - // Generate hex string - const hexString = this._rules.shouldAnnotate - ? this._toHumanReadableCallData() - : this._toEvmCompatibeCallDataHex(); - return hexString; - } - /** - * There are three types of calldata blocks: Blob, Set and Pointer. - * Scenarios arise where distinct pointers resolve to identical values. - * We optimize by keeping only one such instance of the identical value, and redirecting all pointers here. - * We keep the last such duplicate value because pointers can only be positive (they cannot point backwards). - * - * Example #1: - * function f(string[], string[]) - * f(["foo", "bar", "blitz"], ["foo", "bar", "blitz"]) - * The array ["foo", "bar", "blitz"] will only be included in the calldata once. - * - * Example #2: - * function f(string[], string) - * f(["foo", "bar", "blitz"], "foo") - * The string "foo" will only be included in the calldata once. - * - * Example #3: - * function f((string, uint, bytes), string, uint, bytes) - * f(("foo", 5, "0x05"), "foo", 5, "0x05") - * The string "foo" and bytes "0x05" will only be included in the calldata once. - * The duplicate `uint 5` values cannot be optimized out because they are static values (no pointer points to them). - * - * @TODO #1: - * This optimization strategy handles blocks that are exact duplicates of one another. - * But what if some block is a combination of two other blocks? Or a subset of another block? - * This optimization problem is not much different from the current implemetation. - * Instead of tracking "observed" hashes, at each node we would simply do pattern-matching on the calldata. - * This strategy would be applied after assigning offsets to the tree, rather than before (as in this strategy). - * Note that one consequence of this strategy is pointers may resolve to offsets that are not word-aligned. - * This shouldn't be a problem but further investigation should be done. - * - * @TODO #2: - * To be done as a follow-up to @TODO #1. - * Since we optimize from the bottom-up, we could be affecting the outcome of a later potential optimization. - * For example, what if by removing one duplicate value we miss out on optimizing another block higher in the tree. - * To handle this case, at each node we can store a candidate optimization in a priority queue (sorted by calldata size). - * At the end of traversing the tree, the candidate at the front of the queue will be the most optimal output. - * - */ - private _optimize(): void { - // Step 1/1 Create a reverse iterator (starts from the end of the calldata to the beginning) - if (_.isUndefined(this._root)) { - throw new Error('expected root'); - } - const iterator = new ReverseCalldataIterator(this._root); - // Step 2/2 Iterate over each block, keeping track of which blocks have been seen and pruning redundant blocks. - const blocksByHash: { [key: string]: CalldataBlock } = {}; - for (const block of iterator) { - // If a block is a pointer and its value has already been observed, then update - // the pointer to resolve to the existing value. - if (block instanceof PointerCalldataBlock) { - const dependencyBlockHashBuf = block.getDependency().computeHash(); - const dependencyBlockHash = ethUtil.bufferToHex(dependencyBlockHashBuf); - if (dependencyBlockHash in blocksByHash) { - const blockWithSameHash = blocksByHash[dependencyBlockHash]; - if (blockWithSameHash !== block.getDependency()) { - block.setAlias(blockWithSameHash); - } - } - continue; - } - // This block has not been seen. Record its hash. - const blockHashBuf = block.computeHash(); - const blockHash = ethUtil.bufferToHex(blockHashBuf); - if (!(blockHash in blocksByHash)) { - blocksByHash[blockHash] = block; - } - } - } - private _toEvmCompatibeCallDataHex(): string { - // Sanity check: must have a root block. - if (_.isUndefined(this._root)) { - throw new Error('expected root'); - } - // Construct an array of buffers (one buffer for each block). - const selectorBuffer = ethUtil.toBuffer(this._selector); - const valueBufs: Buffer[] = [selectorBuffer]; - const iterator = new CalldataIterator(this._root); - for (const block of iterator) { - valueBufs.push(block.toBuffer()); - } - // Create hex from buffer array. - const combinedBuffers = Buffer.concat(valueBufs); - const hexValue = ethUtil.bufferToHex(combinedBuffers); - return hexValue; - } - /** - * Returns human-readable calldata. - * - * Example: - * simpleFunction(string[], string[]) - * strings = ["Hello", "World"] - * simpleFunction(strings, strings) - * - * Output: - * 0xbb4f12e3 - * ### simpleFunction - * 0x0 0000000000000000000000000000000000000000000000000000000000000040 ptr<array1> (alias for array2) - * 0x20 0000000000000000000000000000000000000000000000000000000000000040 ptr<array2> - * - * 0x40 0000000000000000000000000000000000000000000000000000000000000002 ### array2 - * 0x60 0000000000000000000000000000000000000000000000000000000000000040 ptr<array2[0]> - * 0x80 0000000000000000000000000000000000000000000000000000000000000080 ptr<array2[1]> - * 0xa0 0000000000000000000000000000000000000000000000000000000000000005 array2[0] - * 0xc0 48656c6c6f000000000000000000000000000000000000000000000000000000 - * 0xe0 0000000000000000000000000000000000000000000000000000000000000005 array2[1] - * 0x100 576f726c64000000000000000000000000000000000000000000000000000000 - */ - private _toHumanReadableCallData(): string { - // Sanity check: must have a root block. - if (_.isUndefined(this._root)) { - throw new Error('expected root'); - } - // Constants for constructing annotated string - const offsetPadding = 10; - const valuePadding = 74; - const namePadding = 80; - const evmWordStartIndex = 0; - const emptySize = 0; - // Construct annotated calldata - let hexValue = `${this._selector}`; - let offset = 0; - const functionName: string = this._root.getName(); - const iterator = new CalldataIterator(this._root); - for (const block of iterator) { - // Process each block 1 word at a time - const size = block.getSizeInBytes(); - const name = block.getName(); - const parentName = block.getParentName(); - const prettyName = name.replace(`${parentName}.`, '').replace(`${functionName}.`, ''); - // Resulting line will be <offsetStr><valueStr><nameStr> - let offsetStr = ''; - let valueStr = ''; - let nameStr = ''; - let lineStr = ''; - if (size === emptySize) { - // This is a Set block with no header. - // For example, a tuple or an array with a defined length. - offsetStr = ' '.repeat(offsetPadding); - valueStr = ' '.repeat(valuePadding); - nameStr = `### ${prettyName.padEnd(namePadding)}`; - lineStr = `\n${offsetStr}${valueStr}${nameStr}`; - } else { - // This block has at least one word of value. - offsetStr = `0x${offset.toString(constants.HEX_BASE)}`.padEnd(offsetPadding); - valueStr = ethUtil - .stripHexPrefix( - ethUtil.bufferToHex( - block.toBuffer().slice(evmWordStartIndex, constants.EVM_WORD_WIDTH_IN_BYTES), - ), - ) - .padEnd(valuePadding); - if (block instanceof SetCalldataBlock) { - nameStr = `### ${prettyName.padEnd(namePadding)}`; - lineStr = `\n${offsetStr}${valueStr}${nameStr}`; - } else { - nameStr = ` ${prettyName.padEnd(namePadding)}`; - lineStr = `${offsetStr}${valueStr}${nameStr}`; - } - } - // This block has a value that is more than 1 word. - for (let j = constants.EVM_WORD_WIDTH_IN_BYTES; j < size; j += constants.EVM_WORD_WIDTH_IN_BYTES) { - offsetStr = `0x${(offset + j).toString(constants.HEX_BASE)}`.padEnd(offsetPadding); - valueStr = ethUtil - .stripHexPrefix( - ethUtil.bufferToHex(block.toBuffer().slice(j, j + constants.EVM_WORD_WIDTH_IN_BYTES)), - ) - .padEnd(valuePadding); - nameStr = ' '.repeat(namePadding); - lineStr = `${lineStr}\n${offsetStr}${valueStr}${nameStr}`; - } - // Append to hex value - hexValue = `${hexValue}\n${lineStr}`; - offset += size; - } - return hexValue; - } -} diff --git a/packages/utils/src/abi_encoder/calldata/calldata_block.ts b/packages/utils/src/abi_encoder/calldata/calldata_block.ts deleted file mode 100644 index 35bd994e5..000000000 --- a/packages/utils/src/abi_encoder/calldata/calldata_block.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as ethUtil from 'ethereumjs-util'; - -export abstract class CalldataBlock { - private readonly _signature: string; - private readonly _parentName: string; - private _name: string; - private _offsetInBytes: number; - private _headerSizeInBytes: number; - private _bodySizeInBytes: number; - - constructor( - name: string, - signature: string, - parentName: string, - headerSizeInBytes: number, - bodySizeInBytes: number, - ) { - this._name = name; - this._signature = signature; - this._parentName = parentName; - this._offsetInBytes = 0; - this._headerSizeInBytes = headerSizeInBytes; - this._bodySizeInBytes = bodySizeInBytes; - } - - protected _setHeaderSize(headerSizeInBytes: number): void { - this._headerSizeInBytes = headerSizeInBytes; - } - - protected _setBodySize(bodySizeInBytes: number): void { - this._bodySizeInBytes = bodySizeInBytes; - } - - protected _setName(name: string): void { - this._name = name; - } - - public getName(): string { - return this._name; - } - - public getParentName(): string { - return this._parentName; - } - - public getSignature(): string { - return this._signature; - } - public getHeaderSizeInBytes(): number { - return this._headerSizeInBytes; - } - - public getBodySizeInBytes(): number { - return this._bodySizeInBytes; - } - - public getSizeInBytes(): number { - return this.getHeaderSizeInBytes() + this.getBodySizeInBytes(); - } - - public getOffsetInBytes(): number { - return this._offsetInBytes; - } - - public setOffset(offsetInBytes: number): void { - this._offsetInBytes = offsetInBytes; - } - - public computeHash(): Buffer { - const rawData = this.getRawData(); - const hash = ethUtil.sha3(rawData); - return hash; - } - - public abstract toBuffer(): Buffer; - public abstract getRawData(): Buffer; -} diff --git a/packages/utils/src/abi_encoder/calldata/iterator.ts b/packages/utils/src/abi_encoder/calldata/iterator.ts deleted file mode 100644 index 333b32b4f..000000000 --- a/packages/utils/src/abi_encoder/calldata/iterator.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* tslint:disable max-classes-per-file */ -import * as _ from 'lodash'; - -import { Queue } from '../utils/queue'; - -import { BlobCalldataBlock } from './blocks/blob'; -import { PointerCalldataBlock } from './blocks/pointer'; -import { SetCalldataBlock } from './blocks/set'; -import { CalldataBlock } from './calldata_block'; - -/** - * Iterator class for Calldata Blocks. Blocks follows the order - * they should be put into calldata that is passed to he EVM. - * - * Example #1: - * Let root = Set { - * Blob{} A, - * Pointer { - * Blob{} a - * } B, - * Blob{} C - * } - * It will iterate as follows: [A, B, C, B.a] - * - * Example #2: - * Let root = Set { - * Blob{} A, - * Pointer { - * Blob{} a - * Pointer { - * Blob{} b - * } - * } B, - * Pointer { - * Blob{} c - * } C - * } - * It will iterate as follows: [A, B, C, B.a, B.b, C.c] - */ -abstract class BaseIterator implements Iterable<CalldataBlock> { - protected readonly _root: CalldataBlock; - protected readonly _queue: Queue<CalldataBlock>; - - private static _createQueue(block: CalldataBlock): Queue<CalldataBlock> { - const queue = new Queue<CalldataBlock>(); - // Base case - if (!(block instanceof SetCalldataBlock)) { - queue.pushBack(block); - return queue; - } - // This is a set; add members - const set = block; - _.eachRight(set.getMembers(), (member: CalldataBlock) => { - queue.mergeFront(BaseIterator._createQueue(member)); - }); - // Add children - _.each(set.getMembers(), (member: CalldataBlock) => { - // Traverse child if it is a unique pointer. - // A pointer that is an alias for another pointer is ignored. - if (member instanceof PointerCalldataBlock && _.isUndefined(member.getAlias())) { - const dependency = member.getDependency(); - queue.mergeBack(BaseIterator._createQueue(dependency)); - } - }); - // Put set block at the front of the queue - queue.pushFront(set); - return queue; - } - - public constructor(root: CalldataBlock) { - this._root = root; - this._queue = BaseIterator._createQueue(root); - } - - public [Symbol.iterator](): { next: () => IteratorResult<CalldataBlock> } { - return { - next: () => { - const nextBlock = this.nextBlock(); - if (!_.isUndefined(nextBlock)) { - return { - value: nextBlock, - done: false, - }; - } - return { - done: true, - value: new BlobCalldataBlock('', '', '', new Buffer('')), - }; - }, - }; - } - - public abstract nextBlock(): CalldataBlock | undefined; -} - -export class CalldataIterator extends BaseIterator { - public constructor(root: CalldataBlock) { - super(root); - } - - public nextBlock(): CalldataBlock | undefined { - return this._queue.popFront(); - } -} - -export class ReverseCalldataIterator extends BaseIterator { - public constructor(root: CalldataBlock) { - super(root); - } - - public nextBlock(): CalldataBlock | undefined { - return this._queue.popBack(); - } -} diff --git a/packages/utils/src/abi_encoder/calldata/raw_calldata.ts b/packages/utils/src/abi_encoder/calldata/raw_calldata.ts deleted file mode 100644 index 189841989..000000000 --- a/packages/utils/src/abi_encoder/calldata/raw_calldata.ts +++ /dev/null @@ -1,82 +0,0 @@ -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { constants } from '../utils/constants'; -import { Queue } from '../utils/queue'; - -export class RawCalldata { - private static readonly _INITIAL_OFFSET = 0; - private readonly _value: Buffer; - private readonly _selector: string; - private readonly _scopes: Queue<number>; - private _offset: number; - - public constructor(value: string | Buffer, hasSelector: boolean = true) { - // Sanity check - if (typeof value === 'string' && !_.startsWith(value, '0x')) { - throw new Error(`Expected raw calldata to start with '0x'`); - } - // Construct initial values - this._value = ethUtil.toBuffer(value); - this._selector = '0x'; - this._scopes = new Queue<number>(); - this._scopes.pushBack(RawCalldata._INITIAL_OFFSET); - this._offset = RawCalldata._INITIAL_OFFSET; - // If there's a selector then slice it - if (hasSelector) { - const selectorBuf = this._value.slice(constants.HEX_SELECTOR_LENGTH_IN_BYTES); - this._value = this._value.slice(constants.HEX_SELECTOR_LENGTH_IN_BYTES); - this._selector = ethUtil.bufferToHex(selectorBuf); - } - } - - public popBytes(lengthInBytes: number): Buffer { - const value = this._value.slice(this._offset, this._offset + lengthInBytes); - this.setOffset(this._offset + lengthInBytes); - return value; - } - - public popWord(): Buffer { - const wordInBytes = 32; - return this.popBytes(wordInBytes); - } - - public popWords(length: number): Buffer { - const wordInBytes = 32; - return this.popBytes(length * wordInBytes); - } - - public readBytes(from: number, to: number): Buffer { - const value = this._value.slice(from, to); - return value; - } - - public setOffset(offsetInBytes: number): void { - this._offset = offsetInBytes; - } - - public startScope(): void { - this._scopes.pushFront(this._offset); - } - - public endScope(): void { - this._scopes.popFront(); - } - - public getOffset(): number { - return this._offset; - } - - public toAbsoluteOffset(relativeOffset: number): number { - const scopeOffset = this._scopes.peekFront(); - if (_.isUndefined(scopeOffset)) { - throw new Error(`Tried to access undefined scope.`); - } - const absoluteOffset = relativeOffset + scopeOffset; - return absoluteOffset; - } - - public getSelector(): string { - return this._selector; - } -} diff --git a/packages/utils/src/abi_encoder/evm_data_type_factory.ts b/packages/utils/src/abi_encoder/evm_data_type_factory.ts deleted file mode 100644 index 268649148..000000000 --- a/packages/utils/src/abi_encoder/evm_data_type_factory.ts +++ /dev/null @@ -1,165 +0,0 @@ -/* tslint:disable max-classes-per-file */ -import { DataItem, MethodAbi } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { generateDataItemsFromSignature } from './utils/signature_parser'; - -import { DataType } from './abstract_data_types/data_type'; -import { DataTypeFactory } from './abstract_data_types/interfaces'; -import { AddressDataType } from './evm_data_types/address'; -import { ArrayDataType } from './evm_data_types/array'; -import { BoolDataType } from './evm_data_types/bool'; -import { DynamicBytesDataType } from './evm_data_types/dynamic_bytes'; -import { IntDataType } from './evm_data_types/int'; -import { MethodDataType } from './evm_data_types/method'; -import { PointerDataType } from './evm_data_types/pointer'; -import { StaticBytesDataType } from './evm_data_types/static_bytes'; -import { StringDataType } from './evm_data_types/string'; -import { TupleDataType } from './evm_data_types/tuple'; -import { UIntDataType } from './evm_data_types/uint'; - -export class Address extends AddressDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class Bool extends BoolDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class Int extends IntDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class UInt extends UIntDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class StaticBytes extends StaticBytesDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class DynamicBytes extends DynamicBytesDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class String extends StringDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class Pointer extends PointerDataType { - public constructor(destDataType: DataType, parentDataType: DataType) { - super(destDataType, parentDataType, EvmDataTypeFactory.getInstance()); - } -} - -export class Tuple extends TupleDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class Array extends ArrayDataType { - public constructor(dataItem: DataItem) { - super(dataItem, EvmDataTypeFactory.getInstance()); - } -} - -export class Method extends MethodDataType { - public constructor(abi: MethodAbi) { - super(abi, EvmDataTypeFactory.getInstance()); - } -} - -/* tslint:disable no-construct */ -export class EvmDataTypeFactory implements DataTypeFactory { - private static _instance: DataTypeFactory; - - public static getInstance(): DataTypeFactory { - if (!EvmDataTypeFactory._instance) { - EvmDataTypeFactory._instance = new EvmDataTypeFactory(); - } - return EvmDataTypeFactory._instance; - } - - /* tslint:disable prefer-function-over-method */ - public create(dataItem: DataItem, parentDataType?: DataType): DataType { - // Create data type - let dataType: undefined | DataType; - if (Array.matchType(dataItem.type)) { - dataType = new Array(dataItem); - } else if (Address.matchType(dataItem.type)) { - dataType = new Address(dataItem); - } else if (Bool.matchType(dataItem.type)) { - dataType = new Bool(dataItem); - } else if (Int.matchType(dataItem.type)) { - dataType = new Int(dataItem); - } else if (UInt.matchType(dataItem.type)) { - dataType = new UInt(dataItem); - } else if (StaticBytes.matchType(dataItem.type)) { - dataType = new StaticBytes(dataItem); - } else if (Tuple.matchType(dataItem.type)) { - dataType = new Tuple(dataItem); - } else if (DynamicBytes.matchType(dataItem.type)) { - dataType = new DynamicBytes(dataItem); - } else if (String.matchType(dataItem.type)) { - dataType = new String(dataItem); - } - // @TODO: DataTypeement Fixed/UFixed types - if (_.isUndefined(dataType)) { - throw new Error(`Unrecognized data type: '${dataItem.type}'`); - } else if (!_.isUndefined(parentDataType) && !dataType.isStatic()) { - const pointerToDataType = new Pointer(dataType, parentDataType); - return pointerToDataType; - } - return dataType; - } - /* tslint:enable prefer-function-over-method */ - - private constructor() {} -} - -/** - * Convenience function for creating a DataType from different inputs. - * @param input A single or set of DataItem or a DataType signature. - * A signature in the form of '<type>' is interpreted as a `DataItem` - * For example, 'string' is interpreted as {type: 'string'} - * A signature in the form '(<type1>, <type2>, ..., <typen>)' is interpreted as `DataItem[]` - * For eaxmple, '(string, uint256)' is interpreted as [{type: 'string'}, {type: 'uint256'}] - * @return DataType corresponding to input. - */ -export function create(input: DataItem | DataItem[] | string): DataType { - // Handle different types of input - const isSignature = typeof input === 'string'; - const isTupleSignature = isSignature && (input as string).startsWith('('); - const shouldParseAsTuple = isTupleSignature || _.isArray(input); - // Create input `dataItem` - let dataItem: DataItem; - if (shouldParseAsTuple) { - const dataItems = isSignature ? generateDataItemsFromSignature(input as string) : (input as DataItem[]); - dataItem = { - name: '', - type: 'tuple', - components: dataItems, - }; - } else { - dataItem = isSignature ? generateDataItemsFromSignature(input as string)[0] : (input as DataItem); - } - // Create data type - const dataType = EvmDataTypeFactory.getInstance().create(dataItem); - return dataType; -} -/* tslint:enable no-construct */ diff --git a/packages/utils/src/abi_encoder/evm_data_types/address.ts b/packages/utils/src/abi_encoder/evm_data_types/address.ts deleted file mode 100644 index 2278830eb..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/address.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { DataItem, SolidityTypes } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractBlobDataType } from '../abstract_data_types/types/blob'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; - -export class AddressDataType extends AbstractBlobDataType { - private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; - private static readonly _ADDRESS_SIZE_IN_BYTES = 20; - private static readonly _DECODED_ADDRESS_OFFSET_IN_BYTES = - constants.EVM_WORD_WIDTH_IN_BYTES - AddressDataType._ADDRESS_SIZE_IN_BYTES; - - public static matchType(type: string): boolean { - return type === SolidityTypes.Address; - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - super(dataItem, dataTypeFactory, AddressDataType._SIZE_KNOWN_AT_COMPILE_TIME); - if (!AddressDataType.matchType(dataItem.type)) { - throw new Error(`Tried to instantiate Address with bad input: ${dataItem}`); - } - } - - // Disable prefer-function-over-method for inherited abstract methods. - /* tslint:disable prefer-function-over-method */ - public encodeValue(value: string): Buffer { - if (!ethUtil.isValidAddress(value)) { - throw new Error(`Invalid address: '${value}'`); - } - const valueBuf = ethUtil.toBuffer(value); - const encodedValueBuf = ethUtil.setLengthLeft(valueBuf, constants.EVM_WORD_WIDTH_IN_BYTES); - return encodedValueBuf; - } - - public decodeValue(calldata: RawCalldata): string { - const valueBufPadded = calldata.popWord(); - const valueBuf = valueBufPadded.slice(AddressDataType._DECODED_ADDRESS_OFFSET_IN_BYTES); - const value = ethUtil.bufferToHex(valueBuf); - const valueLowercase = _.toLower(value); - return valueLowercase; - } - - public getSignatureType(): string { - return SolidityTypes.Address; - } - /* tslint:enable prefer-function-over-method */ -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/array.ts b/packages/utils/src/abi_encoder/evm_data_types/array.ts deleted file mode 100644 index d9607f47e..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/array.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractSetDataType } from '../abstract_data_types/types/set'; -import { constants } from '../utils/constants'; - -export class ArrayDataType extends AbstractSetDataType { - private static readonly _MATCHER = RegExp('^(.+)\\[([0-9]*)\\]$'); - private readonly _elementType: string; - - public static matchType(type: string): boolean { - return ArrayDataType._MATCHER.test(type); - } - - private static _decodeElementTypeAndLengthFromType(type: string): [string, undefined | number] { - const matches = ArrayDataType._MATCHER.exec(type); - if (_.isNull(matches) || matches.length !== 3) { - throw new Error(`Could not parse array: ${type}`); - } else if (_.isUndefined(matches[1])) { - throw new Error(`Could not parse array type: ${type}`); - } else if (_.isUndefined(matches[2])) { - throw new Error(`Could not parse array length: ${type}`); - } - const arrayElementType = matches[1]; - const arrayLength = _.isEmpty(matches[2]) ? undefined : parseInt(matches[2], constants.DEC_BASE); - return [arrayElementType, arrayLength]; - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - // Construct parent - const isArray = true; - const [arrayElementType, arrayLength] = ArrayDataType._decodeElementTypeAndLengthFromType(dataItem.type); - super(dataItem, dataTypeFactory, isArray, arrayLength, arrayElementType); - // Set array properties - this._elementType = arrayElementType; - } - - public getSignatureType(): string { - return this._computeSignature(false); - } - - public getSignature(isDetailed?: boolean): string { - if (_.isEmpty(this.getDataItem().name) || !isDetailed) { - return this.getSignatureType(); - } - const name = this.getDataItem().name; - const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); - const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; - const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 1) : name; - const detailedSignature = `${shortName} ${this._computeSignature(isDetailed)}`; - return detailedSignature; - } - - private _computeSignature(isDetailed?: boolean): string { - // Compute signature for a single array element - const elementDataItem: DataItem = { - type: this._elementType, - name: '', - }; - const elementComponents = this.getDataItem().components; - if (!_.isUndefined(elementComponents)) { - elementDataItem.components = elementComponents; - } - const elementDataType = this.getFactory().create(elementDataItem); - const elementSignature = elementDataType.getSignature(isDetailed); - // Construct signature for array of type `element` - if (_.isUndefined(this._arrayLength)) { - return `${elementSignature}[]`; - } else { - return `${elementSignature}[${this._arrayLength}]`; - } - } -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/bool.ts b/packages/utils/src/abi_encoder/evm_data_types/bool.ts deleted file mode 100644 index 23298bc88..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/bool.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { DataItem, SolidityTypes } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { BigNumber } from '../../configured_bignumber'; -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractBlobDataType } from '../abstract_data_types/types/blob'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; - -export class BoolDataType extends AbstractBlobDataType { - private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; - - public static matchType(type: string): boolean { - return type === SolidityTypes.Bool; - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - super(dataItem, dataTypeFactory, BoolDataType._SIZE_KNOWN_AT_COMPILE_TIME); - if (!BoolDataType.matchType(dataItem.type)) { - throw new Error(`Tried to instantiate Bool with bad input: ${dataItem}`); - } - } - - // Disable prefer-function-over-method for inherited abstract methods. - /* tslint:disable prefer-function-over-method */ - public encodeValue(value: boolean): Buffer { - const encodedValue = value ? '0x1' : '0x0'; - const encodedValueBuf = ethUtil.setLengthLeft( - ethUtil.toBuffer(encodedValue), - constants.EVM_WORD_WIDTH_IN_BYTES, - ); - return encodedValueBuf; - } - - public decodeValue(calldata: RawCalldata): boolean { - const valueBuf = calldata.popWord(); - const valueHex = ethUtil.bufferToHex(valueBuf); - const valueNumber = new BigNumber(valueHex, constants.HEX_BASE); - if (!(valueNumber.isEqualTo(0) || valueNumber.isEqualTo(1))) { - throw new Error(`Failed to decode boolean. Expected 0x0 or 0x1, got ${valueHex}`); - } - /* tslint:disable boolean-naming */ - const value: boolean = !valueNumber.isEqualTo(0); - /* tslint:enable boolean-naming */ - return value; - } - - public getSignatureType(): string { - return SolidityTypes.Bool; - } - /* tslint:enable prefer-function-over-method */ -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts b/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts deleted file mode 100644 index fa38b63c0..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/dynamic_bytes.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { DataItem, SolidityTypes } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractBlobDataType } from '../abstract_data_types/types/blob'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; - -export class DynamicBytesDataType extends AbstractBlobDataType { - private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = false; - - public static matchType(type: string): boolean { - return type === SolidityTypes.Bytes; - } - - private static _sanityCheckValue(value: string | Buffer): void { - if (typeof value !== 'string') { - return; - } - if (!_.startsWith(value, '0x')) { - throw new Error(`Tried to encode non-hex value. Value must inlcude '0x' prefix.`); - } else if (value.length % 2 !== 0) { - throw new Error(`Tried to assign ${value}, which is contains a half-byte. Use full bytes only.`); - } - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - super(dataItem, dataTypeFactory, DynamicBytesDataType._SIZE_KNOWN_AT_COMPILE_TIME); - if (!DynamicBytesDataType.matchType(dataItem.type)) { - throw new Error(`Tried to instantiate Dynamic Bytes with bad input: ${dataItem}`); - } - } - - // Disable prefer-function-over-method for inherited abstract methods. - /* tslint:disable prefer-function-over-method */ - public encodeValue(value: string | Buffer): Buffer { - // Encoded value is of the form: <length><value>, with each field padded to be word-aligned. - // 1/3 Construct the length - const valueBuf = ethUtil.toBuffer(value); - const wordsToStoreValuePadded = Math.ceil(valueBuf.byteLength / constants.EVM_WORD_WIDTH_IN_BYTES); - const bytesToStoreValuePadded = wordsToStoreValuePadded * constants.EVM_WORD_WIDTH_IN_BYTES; - const lengthBuf = ethUtil.toBuffer(valueBuf.byteLength); - const lengthBufPadded = ethUtil.setLengthLeft(lengthBuf, constants.EVM_WORD_WIDTH_IN_BYTES); - // 2/3 Construct the value - DynamicBytesDataType._sanityCheckValue(value); - const valueBufPadded = ethUtil.setLengthRight(valueBuf, bytesToStoreValuePadded); - // 3/3 Combine length and value - const encodedValue = Buffer.concat([lengthBufPadded, valueBufPadded]); - return encodedValue; - } - - public decodeValue(calldata: RawCalldata): string { - // Encoded value is of the form: <length><value>, with each field padded to be word-aligned. - // 1/2 Decode length - const lengthBuf = calldata.popWord(); - const lengthHex = ethUtil.bufferToHex(lengthBuf); - const length = parseInt(lengthHex, constants.HEX_BASE); - // 2/2 Decode value - const wordsToStoreValuePadded = Math.ceil(length / constants.EVM_WORD_WIDTH_IN_BYTES); - const valueBufPadded = calldata.popWords(wordsToStoreValuePadded); - const valueBuf = valueBufPadded.slice(0, length); - const value = ethUtil.bufferToHex(valueBuf); - DynamicBytesDataType._sanityCheckValue(value); - return value; - } - - public getSignatureType(): string { - return SolidityTypes.Bytes; - } - /* tslint:enable prefer-function-over-method */ -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/int.ts b/packages/utils/src/abi_encoder/evm_data_types/int.ts deleted file mode 100644 index f8be1f778..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/int.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { DataItem, SolidityTypes } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { BigNumber } from '../../configured_bignumber'; -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractBlobDataType } from '../abstract_data_types/types/blob'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; -import * as EncoderMath from '../utils/math'; - -export class IntDataType extends AbstractBlobDataType { - private static readonly _MATCHER = RegExp( - '^int(8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256){0,1}$', - ); - private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; - private static readonly _MAX_WIDTH: number = 256; - private static readonly _DEFAULT_WIDTH: number = IntDataType._MAX_WIDTH; - private readonly _width: number; - private readonly _minValue: BigNumber; - private readonly _maxValue: BigNumber; - - public static matchType(type: string): boolean { - return IntDataType._MATCHER.test(type); - } - - private static _decodeWidthFromType(type: string): number { - const matches = IntDataType._MATCHER.exec(type); - const width = - !_.isNull(matches) && matches.length === 2 && !_.isUndefined(matches[1]) - ? parseInt(matches[1], constants.DEC_BASE) - : IntDataType._DEFAULT_WIDTH; - return width; - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - super(dataItem, dataTypeFactory, IntDataType._SIZE_KNOWN_AT_COMPILE_TIME); - if (!IntDataType.matchType(dataItem.type)) { - throw new Error(`Tried to instantiate Int with bad input: ${dataItem}`); - } - this._width = IntDataType._decodeWidthFromType(dataItem.type); - this._minValue = new BigNumber(2).exponentiatedBy(this._width - 1).times(-1); - this._maxValue = new BigNumber(2).exponentiatedBy(this._width - 1).minus(1); - } - - public encodeValue(value: BigNumber | string | number): Buffer { - const encodedValue = EncoderMath.safeEncodeNumericValue(value, this._minValue, this._maxValue); - return encodedValue; - } - - public decodeValue(calldata: RawCalldata): BigNumber | number { - const valueBuf = calldata.popWord(); - const value = EncoderMath.safeDecodeNumericValue(valueBuf, this._minValue, this._maxValue); - const numberOfBytesInUint8 = 8; - if (this._width === numberOfBytesInUint8) { - return value.toNumber(); - } - return value; - } - - public getSignatureType(): string { - return `${SolidityTypes.Int}${this._width}`; - } -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/method.ts b/packages/utils/src/abi_encoder/evm_data_types/method.ts deleted file mode 100644 index c852a0fdf..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/method.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { DataItem, MethodAbi } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { DataType } from '../abstract_data_types/data_type'; -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractSetDataType } from '../abstract_data_types/types/set'; -import { constants } from '../utils/constants'; -import { DecodingRules, EncodingRules } from '../utils/rules'; - -import { TupleDataType } from './tuple'; - -export class MethodDataType extends AbstractSetDataType { - private readonly _methodSignature: string; - private readonly _methodSelector: string; - private readonly _returnDataType: DataType; - - public constructor(abi: MethodAbi, dataTypeFactory: DataTypeFactory) { - const methodDataItem = { type: 'method', name: abi.name, components: abi.inputs }; - super(methodDataItem, dataTypeFactory); - this._methodSignature = this._computeSignature(); - this._methodSelector = this._computeSelector(); - const returnDataItem: DataItem = { type: 'tuple', name: abi.name, components: abi.outputs }; - this._returnDataType = new TupleDataType(returnDataItem, this.getFactory()); - } - - public encode(value: any, rules?: EncodingRules): string { - const calldata = super.encode(value, rules, this._methodSelector); - return calldata; - } - - public decode(calldata: string, rules?: DecodingRules): any[] | object { - const value = super.decode(calldata, rules, this._methodSelector); - return value; - } - - public encodeReturnValues(value: any, rules?: EncodingRules): string { - const returnData = this._returnDataType.encode(value, rules); - return returnData; - } - - public decodeReturnValues(returndata: string, rules?: DecodingRules): any { - const returnValues = this._returnDataType.decode(returndata, rules); - return returnValues; - } - - public strictDecodeReturnValue<T>(returndata: string, rules?: DecodingRules): T { - const returnValues = this._returnDataType.decode(returndata, rules); - const returnValuesAsArray: any = _.isObject(returnValues) ? _.values(returnValues) : [returnValues]; - switch (returnValuesAsArray.length) { - case 0: - return undefined as any; - case 1: - return returnValuesAsArray[0]; - default: - return returnValuesAsArray; - } - } - - public getSignatureType(): string { - return this._methodSignature; - } - - public getSelector(): string { - return this._methodSelector; - } - - private _computeSignature(): string { - const memberSignature = this._computeSignatureOfMembers(); - const methodSignature = `${this.getDataItem().name}${memberSignature}`; - return methodSignature; - } - - private _computeSelector(): string { - const signature = this._computeSignature(); - const selector = ethUtil.bufferToHex( - ethUtil.toBuffer( - ethUtil - .sha3(signature) - .slice(constants.HEX_SELECTOR_BYTE_OFFSET_IN_CALLDATA, constants.HEX_SELECTOR_LENGTH_IN_BYTES), - ), - ); - return selector; - } -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts b/packages/utils/src/abi_encoder/evm_data_types/pointer.ts deleted file mode 100644 index 250db7c64..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/pointer.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { DataItem } from 'ethereum-types'; - -import { DataType } from '../abstract_data_types/data_type'; -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractPointerDataType } from '../abstract_data_types/types/pointer'; - -export class PointerDataType extends AbstractPointerDataType { - constructor(destDataType: DataType, parentDataType: DataType, dataTypeFactory: DataTypeFactory) { - const destDataItem = destDataType.getDataItem(); - const dataItem: DataItem = { name: `ptr<${destDataItem.name}>`, type: `ptr<${destDataItem.type}>` }; - super(dataItem, dataTypeFactory, destDataType, parentDataType); - } - - public getSignatureType(): string { - return this._destination.getSignature(false); - } - - public getSignature(isDetailed?: boolean): string { - return this._destination.getSignature(isDetailed); - } -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts b/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts deleted file mode 100644 index cbf1957d7..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/static_bytes.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { DataItem, SolidityTypes } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractBlobDataType } from '../abstract_data_types/types/blob'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; - -export class StaticBytesDataType extends AbstractBlobDataType { - private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; - private static readonly _MATCHER = RegExp( - '^(byte|bytes(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32))$', - ); - private static readonly _DEFAULT_WIDTH = 1; - private readonly _width: number; - - public static matchType(type: string): boolean { - return StaticBytesDataType._MATCHER.test(type); - } - - private static _decodeWidthFromType(type: string): number { - const matches = StaticBytesDataType._MATCHER.exec(type); - const width = - !_.isNull(matches) && matches.length === 3 && !_.isUndefined(matches[2]) - ? parseInt(matches[2], constants.DEC_BASE) - : StaticBytesDataType._DEFAULT_WIDTH; - return width; - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - super(dataItem, dataTypeFactory, StaticBytesDataType._SIZE_KNOWN_AT_COMPILE_TIME); - if (!StaticBytesDataType.matchType(dataItem.type)) { - throw new Error(`Tried to instantiate Static Bytes with bad input: ${dataItem}`); - } - this._width = StaticBytesDataType._decodeWidthFromType(dataItem.type); - } - - public getSignatureType(): string { - // Note that `byte` reduces to `bytes1` - return `${SolidityTypes.Bytes}${this._width}`; - } - - public encodeValue(value: string | Buffer): Buffer { - // 1/2 Convert value into a buffer and do bounds checking - this._sanityCheckValue(value); - const valueBuf = ethUtil.toBuffer(value); - // 2/2 Store value as hex - const valuePadded = ethUtil.setLengthRight(valueBuf, constants.EVM_WORD_WIDTH_IN_BYTES); - return valuePadded; - } - - public decodeValue(calldata: RawCalldata): string { - const valueBufPadded = calldata.popWord(); - const valueBuf = valueBufPadded.slice(0, this._width); - const value = ethUtil.bufferToHex(valueBuf); - this._sanityCheckValue(value); - return value; - } - - private _sanityCheckValue(value: string | Buffer): void { - if (typeof value === 'string') { - if (!_.startsWith(value, '0x')) { - throw new Error(`Tried to encode non-hex value. Value must inlcude '0x' prefix.`); - } else if (value.length % 2 !== 0) { - throw new Error(`Tried to assign ${value}, which is contains a half-byte. Use full bytes only.`); - } - } - const valueBuf = ethUtil.toBuffer(value); - if (valueBuf.byteLength > this._width) { - throw new Error( - `Tried to assign ${value} (${ - valueBuf.byteLength - } bytes), which exceeds max bytes that can be stored in a ${this.getSignature()}`, - ); - } - } -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/string.ts b/packages/utils/src/abi_encoder/evm_data_types/string.ts deleted file mode 100644 index 97ac46442..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/string.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { DataItem, SolidityTypes } from 'ethereum-types'; -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractBlobDataType } from '../abstract_data_types/types/blob'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; - -export class StringDataType extends AbstractBlobDataType { - private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = false; - - public static matchType(type: string): boolean { - return type === SolidityTypes.String; - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - super(dataItem, dataTypeFactory, StringDataType._SIZE_KNOWN_AT_COMPILE_TIME); - if (!StringDataType.matchType(dataItem.type)) { - throw new Error(`Tried to instantiate String with bad input: ${dataItem}`); - } - } - - // Disable prefer-function-over-method for inherited abstract methods. - /* tslint:disable prefer-function-over-method */ - public encodeValue(value: string): Buffer { - // Encoded value is of the form: <length><value>, with each field padded to be word-aligned. - // 1/3 Construct the length - const wordsToStoreValuePadded = Math.ceil(value.length / constants.EVM_WORD_WIDTH_IN_BYTES); - const bytesToStoreValuePadded = wordsToStoreValuePadded * constants.EVM_WORD_WIDTH_IN_BYTES; - const lengthBuf = ethUtil.toBuffer(value.length); - const lengthBufPadded = ethUtil.setLengthLeft(lengthBuf, constants.EVM_WORD_WIDTH_IN_BYTES); - // 2/3 Construct the value - const valueBuf = new Buffer(value); - const valueBufPadded = ethUtil.setLengthRight(valueBuf, bytesToStoreValuePadded); - // 3/3 Combine length and value - const encodedValue = Buffer.concat([lengthBufPadded, valueBufPadded]); - return encodedValue; - } - - public decodeValue(calldata: RawCalldata): string { - // Encoded value is of the form: <length><value>, with each field padded to be word-aligned. - // 1/2 Decode length - const lengthBufPadded = calldata.popWord(); - const lengthHexPadded = ethUtil.bufferToHex(lengthBufPadded); - const length = parseInt(lengthHexPadded, constants.HEX_BASE); - // 2/2 Decode value - const wordsToStoreValuePadded = Math.ceil(length / constants.EVM_WORD_WIDTH_IN_BYTES); - const valueBufPadded = calldata.popWords(wordsToStoreValuePadded); - const valueBuf = valueBufPadded.slice(0, length); - const value = valueBuf.toString('ascii'); - return value; - } - - public getSignatureType(): string { - return SolidityTypes.String; - } - /* tslint:enable prefer-function-over-method */ -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts b/packages/utils/src/abi_encoder/evm_data_types/tuple.ts deleted file mode 100644 index 5000c85e8..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/tuple.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { DataItem, SolidityTypes } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractSetDataType } from '../abstract_data_types/types/set'; - -export class TupleDataType extends AbstractSetDataType { - public static matchType(type: string): boolean { - return type === SolidityTypes.Tuple; - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - super(dataItem, dataTypeFactory); - if (!TupleDataType.matchType(dataItem.type)) { - throw new Error(`Tried to instantiate Tuple with bad input: ${dataItem}`); - } - } - - public getSignatureType(): string { - return this._computeSignatureOfMembers(false); - } - - public getSignature(isDetailed?: boolean): string { - if (_.isEmpty(this.getDataItem().name) || !isDetailed) { - return this.getSignatureType(); - } - const name = this.getDataItem().name; - const lastIndexOfScopeDelimiter = name.lastIndexOf('.'); - const isScopedName = !_.isUndefined(lastIndexOfScopeDelimiter) && lastIndexOfScopeDelimiter > 0; - const shortName = isScopedName ? name.substr((lastIndexOfScopeDelimiter as number) + 1) : name; - const detailedSignature = `${shortName} ${this._computeSignatureOfMembers(isDetailed)}`; - return detailedSignature; - } -} diff --git a/packages/utils/src/abi_encoder/evm_data_types/uint.ts b/packages/utils/src/abi_encoder/evm_data_types/uint.ts deleted file mode 100644 index a82aa789e..000000000 --- a/packages/utils/src/abi_encoder/evm_data_types/uint.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { DataItem, SolidityTypes } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { BigNumber } from '../../configured_bignumber'; -import { DataTypeFactory } from '../abstract_data_types/interfaces'; -import { AbstractBlobDataType } from '../abstract_data_types/types/blob'; -import { RawCalldata } from '../calldata/raw_calldata'; -import { constants } from '../utils/constants'; -import * as EncoderMath from '../utils/math'; - -export class UIntDataType extends AbstractBlobDataType { - private static readonly _MATCHER = RegExp( - '^uint(8|16|24|32|40|48|56|64|72|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256){0,1}$', - ); - private static readonly _SIZE_KNOWN_AT_COMPILE_TIME: boolean = true; - private static readonly _MAX_WIDTH: number = 256; - private static readonly _DEFAULT_WIDTH: number = UIntDataType._MAX_WIDTH; - private static readonly _MIN_VALUE = new BigNumber(0); - private readonly _width: number; - private readonly _maxValue: BigNumber; - - public static matchType(type: string): boolean { - return UIntDataType._MATCHER.test(type); - } - - private static _decodeWidthFromType(type: string): number { - const matches = UIntDataType._MATCHER.exec(type); - const width = - !_.isNull(matches) && matches.length === 2 && !_.isUndefined(matches[1]) - ? parseInt(matches[1], constants.DEC_BASE) - : UIntDataType._DEFAULT_WIDTH; - return width; - } - - public constructor(dataItem: DataItem, dataTypeFactory: DataTypeFactory) { - super(dataItem, dataTypeFactory, UIntDataType._SIZE_KNOWN_AT_COMPILE_TIME); - if (!UIntDataType.matchType(dataItem.type)) { - throw new Error(`Tried to instantiate UInt with bad input: ${dataItem}`); - } - this._width = UIntDataType._decodeWidthFromType(dataItem.type); - this._maxValue = new BigNumber(2).exponentiatedBy(this._width).minus(1); - } - - public encodeValue(value: BigNumber | string | number): Buffer { - const encodedValue = EncoderMath.safeEncodeNumericValue(value, UIntDataType._MIN_VALUE, this._maxValue); - return encodedValue; - } - - public decodeValue(calldata: RawCalldata): BigNumber | number { - const valueBuf = calldata.popWord(); - const value = EncoderMath.safeDecodeNumericValue(valueBuf, UIntDataType._MIN_VALUE, this._maxValue); - const numberOfBytesInUint8 = 8; - if (this._width === numberOfBytesInUint8) { - return value.toNumber(); - } - return value; - } - - public getSignatureType(): string { - return `${SolidityTypes.Uint}${this._width}`; - } -} diff --git a/packages/utils/src/abi_encoder/index.ts b/packages/utils/src/abi_encoder/index.ts deleted file mode 100644 index cfacfe075..000000000 --- a/packages/utils/src/abi_encoder/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -export { EncodingRules, DecodingRules } from './utils/rules'; -export { - Address, - Array, - Bool, - DynamicBytes, - Int, - Method, - Pointer, - StaticBytes, - String, - Tuple, - UInt, - create, -} from './evm_data_type_factory'; -export { DataType } from './abstract_data_types/data_type'; diff --git a/packages/utils/src/abi_encoder/utils/constants.ts b/packages/utils/src/abi_encoder/utils/constants.ts deleted file mode 100644 index fc586f295..000000000 --- a/packages/utils/src/abi_encoder/utils/constants.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { DecodingRules, EncodingRules } from './rules'; - -export const constants = { - EVM_WORD_WIDTH_IN_BYTES: 32, - EVM_WORD_WIDTH_IN_BITS: 256, - HEX_BASE: 16, - DEC_BASE: 10, - BIN_BASE: 2, - HEX_SELECTOR_LENGTH_IN_CHARS: 10, - HEX_SELECTOR_LENGTH_IN_BYTES: 4, - HEX_SELECTOR_BYTE_OFFSET_IN_CALLDATA: 0, - // Disable no-object-literal-type-assertion so we can enforce cast - /* tslint:disable no-object-literal-type-assertion */ - DEFAULT_DECODING_RULES: { shouldConvertStructsToObjects: true } as DecodingRules, - DEFAULT_ENCODING_RULES: { shouldOptimize: true, shouldAnnotate: false } as EncodingRules, - /* tslint:enable no-object-literal-type-assertion */ -}; diff --git a/packages/utils/src/abi_encoder/utils/math.ts b/packages/utils/src/abi_encoder/utils/math.ts deleted file mode 100644 index a2a79e2a8..000000000 --- a/packages/utils/src/abi_encoder/utils/math.ts +++ /dev/null @@ -1,113 +0,0 @@ -import * as ethUtil from 'ethereumjs-util'; -import * as _ from 'lodash'; - -import { BigNumber } from '../../configured_bignumber'; -import { constants } from '../utils/constants'; - -function sanityCheckBigNumberRange( - value_: BigNumber | string | number, - minValue: BigNumber, - maxValue: BigNumber, -): void { - const value = new BigNumber(value_, 10); - if (value.isGreaterThan(maxValue)) { - throw new Error(`Tried to assign value of ${value}, which exceeds max value of ${maxValue}`); - } else if (value.isLessThan(minValue)) { - throw new Error(`Tried to assign value of ${value}, which exceeds min value of ${minValue}`); - } else if (value.isNaN()) { - throw new Error(`Tried to assign NaN value`); - } -} -function bigNumberToPaddedBuffer(value: BigNumber): Buffer { - const valueHex = `0x${value.toString(constants.HEX_BASE)}`; - const valueBuf = ethUtil.toBuffer(valueHex); - const valueBufPadded = ethUtil.setLengthLeft(valueBuf, constants.EVM_WORD_WIDTH_IN_BYTES); - return valueBufPadded; -} -/** - * Takes a numeric value and returns its ABI-encoded value - * @param value_ The value to encode. - * @return ABI Encoded value - */ -export function encodeNumericValue(value_: BigNumber | string | number): Buffer { - const value = new BigNumber(value_, 10); - // Case 1/2: value is non-negative - if (value.isGreaterThanOrEqualTo(0)) { - const encodedPositiveValue = bigNumberToPaddedBuffer(value); - return encodedPositiveValue; - } - // Case 2/2: Value is negative - // Use two's-complement to encode the value - // Step 1/3: Convert negative value to positive binary string - const valueBin = value.times(-1).toString(constants.BIN_BASE); - // Step 2/3: Invert binary value - let invertedValueBin = '1'.repeat(constants.EVM_WORD_WIDTH_IN_BITS - valueBin.length); - _.each(valueBin, (bit: string) => { - invertedValueBin += bit === '1' ? '0' : '1'; - }); - const invertedValue = new BigNumber(invertedValueBin, constants.BIN_BASE); - // Step 3/3: Add 1 to inverted value - const negativeValue = invertedValue.plus(1); - const encodedValue = bigNumberToPaddedBuffer(negativeValue); - return encodedValue; -} -/** - * Takes a numeric value and returns its ABI-encoded value. - * Performs an additional sanity check, given the min/max allowed value. - * @param value_ The value to encode. - * @return ABI Encoded value - */ -export function safeEncodeNumericValue( - value: BigNumber | string | number, - minValue: BigNumber, - maxValue: BigNumber, -): Buffer { - sanityCheckBigNumberRange(value, minValue, maxValue); - const encodedValue = encodeNumericValue(value); - return encodedValue; -} -/** - * Takes an ABI-encoded numeric value and returns its decoded value as a BigNumber. - * @param encodedValue The encoded numeric value. - * @param minValue The minimum possible decoded value. - * @return ABI Decoded value - */ -export function decodeNumericValue(encodedValue: Buffer, minValue: BigNumber): BigNumber { - const valueHex = ethUtil.bufferToHex(encodedValue); - // Case 1/3: value is definitely non-negative because of numeric boundaries - const value = new BigNumber(valueHex, constants.HEX_BASE); - if (!minValue.isLessThan(0)) { - return value; - } - // Case 2/3: value is non-negative because there is no leading 1 (encoded as two's-complement) - const valueBin = value.toString(constants.BIN_BASE); - const isValueNegative = valueBin.length === constants.EVM_WORD_WIDTH_IN_BITS && _.startsWith(valueBin[0], '1'); - if (!isValueNegative) { - return value; - } - // Case 3/3: value is negative - // Step 1/3: Invert b inary value - let invertedValueBin = ''; - _.each(valueBin, (bit: string) => { - invertedValueBin += bit === '1' ? '0' : '1'; - }); - const invertedValue = new BigNumber(invertedValueBin, constants.BIN_BASE); - // Step 2/3: Add 1 to inverted value - // The result is the two's-complement representation of the input value. - const positiveValue = invertedValue.plus(1); - // Step 3/3: Invert positive value to get the negative value - const negativeValue = positiveValue.times(-1); - return negativeValue; -} -/** - * Takes an ABI-encoded numeric value and returns its decoded value as a BigNumber. - * Performs an additional sanity check, given the min/max allowed value. - * @param encodedValue The encoded numeric value. - * @param minValue The minimum possible decoded value. - * @return ABI Decoded value - */ -export function safeDecodeNumericValue(encodedValue: Buffer, minValue: BigNumber, maxValue: BigNumber): BigNumber { - const value = decodeNumericValue(encodedValue, minValue); - sanityCheckBigNumberRange(value, minValue, maxValue); - return value; -} diff --git a/packages/utils/src/abi_encoder/utils/queue.ts b/packages/utils/src/abi_encoder/utils/queue.ts deleted file mode 100644 index 53afb7e11..000000000 --- a/packages/utils/src/abi_encoder/utils/queue.ts +++ /dev/null @@ -1,39 +0,0 @@ -export class Queue<T> { - private _store: T[] = []; - - public pushBack(val: T): void { - this._store.push(val); - } - - public pushFront(val: T): void { - this._store.unshift(val); - } - - public popFront(): T | undefined { - return this._store.shift(); - } - - public popBack(): T | undefined { - if (this._store.length === 0) { - return undefined; - } - const backElement = this._store.splice(-1, 1)[0]; - return backElement; - } - - public mergeBack(q: Queue<T>): void { - this._store = this._store.concat(q._store); - } - - public mergeFront(q: Queue<T>): void { - this._store = q._store.concat(this._store); - } - - public getStore(): T[] { - return this._store; - } - - public peekFront(): T | undefined { - return this._store.length >= 0 ? this._store[0] : undefined; - } -} diff --git a/packages/utils/src/abi_encoder/utils/rules.ts b/packages/utils/src/abi_encoder/utils/rules.ts deleted file mode 100644 index c8d83c3ba..000000000 --- a/packages/utils/src/abi_encoder/utils/rules.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface DecodingRules { - shouldConvertStructsToObjects: boolean; -} - -export interface EncodingRules { - shouldOptimize?: boolean; - shouldAnnotate?: boolean; -} diff --git a/packages/utils/src/abi_encoder/utils/signature_parser.ts b/packages/utils/src/abi_encoder/utils/signature_parser.ts deleted file mode 100644 index 315784cea..000000000 --- a/packages/utils/src/abi_encoder/utils/signature_parser.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { DataItem } from 'ethereum-types'; -import * as _ from 'lodash'; - -/** - * Returns an array of DataItem's corresponding to the input signature. - * A signature can be in two forms: '<DataItem.type>' or '(<DataItem1.type>, <DataItem2.type>, ...) - * An example of the first form would be 'address' or 'uint256' - * An example of the second form would be '(address, uint256)' - * Signatures can also include a name field, for example: 'foo address' or '(foo address, bar uint256)' - * @param signature of input DataItems - * @return DataItems derived from input signature - */ -export function generateDataItemsFromSignature(signature: string): DataItem[] { - let trimmedSignature = signature; - if (signature.startsWith('(')) { - if (!signature.endsWith(')')) { - throw new Error(`Failed to generate data item. Must end with ')'`); - } - trimmedSignature = signature.substr(1, signature.length - 2); - } - trimmedSignature += ','; - let isCurrTokenArray = false; - let currTokenArrayModifier = ''; - let isParsingArrayModifier = false; - let currToken = ''; - let parenCount = 0; - let currTokenName = ''; - const dataItems: DataItem[] = []; - for (const char of trimmedSignature) { - // Tokenize the type string while keeping track of parentheses. - switch (char) { - case '(': - parenCount += 1; - currToken += char; - break; - case ')': - parenCount -= 1; - currToken += char; - break; - case '[': - if (parenCount === 0) { - isParsingArrayModifier = true; - isCurrTokenArray = true; - currTokenArrayModifier += '['; - } else { - currToken += char; - } - break; - case ']': - if (parenCount === 0) { - isParsingArrayModifier = false; - currTokenArrayModifier += ']'; - } else { - currToken += char; - } - break; - case ' ': - if (parenCount === 0) { - currTokenName = currToken; - currToken = ''; - } else { - currToken += char; - } - break; - case ',': - if (parenCount === 0) { - // Generate new DataItem from token - const components = currToken.startsWith('(') ? generateDataItemsFromSignature(currToken) : []; - const isTuple = !_.isEmpty(components); - const dataItem: DataItem = { name: currTokenName, type: '' }; - if (isTuple) { - dataItem.type = 'tuple'; - dataItem.components = components; - } else { - dataItem.type = currToken; - } - if (isCurrTokenArray) { - dataItem.type += currTokenArrayModifier; - } - dataItems.push(dataItem); - // reset token state - currTokenName = ''; - currToken = ''; - isCurrTokenArray = false; - currTokenArrayModifier = ''; - break; - } else { - currToken += char; - break; - } - default: - if (isParsingArrayModifier) { - currTokenArrayModifier += char; - } else { - currToken += char; - } - break; - } - } - return dataItems; -} diff --git a/packages/utils/src/abi_utils.ts b/packages/utils/src/abi_utils.ts deleted file mode 100644 index 3e6fc9665..000000000 --- a/packages/utils/src/abi_utils.ts +++ /dev/null @@ -1,229 +0,0 @@ -import { AbiDefinition, AbiType, ContractAbi, DataItem, MethodAbi } from 'ethereum-types'; -import * as _ from 'lodash'; - -import { BigNumber } from './configured_bignumber'; - -type ParamName = null | string | NestedParamName; -interface NestedParamName { - name: string | null; - names: ParamName[]; -} - -// Note(albrow): This function is unexported in ethers.js. Copying it here for -// now. -// Source: https://github.com/ethers-io/ethers.js/blob/884593ab76004a808bf8097e9753fb5f8dcc3067/contracts/interface.js#L30 -function parseEthersParams(params: DataItem[]): { names: ParamName[]; types: string[] } { - const names: ParamName[] = []; - const types: string[] = []; - - params.forEach((param: DataItem) => { - if (param.components != null) { - let suffix = ''; - const arrayBracket = param.type.indexOf('['); - if (arrayBracket >= 0) { - suffix = param.type.substring(arrayBracket); - } - - const result = parseEthersParams(param.components); - names.push({ name: param.name || null, names: result.names }); - types.push(`tuple(${result.types.join(',')})${suffix}`); - } else { - names.push(param.name || null); - types.push(param.type); - } - }); - - return { - names, - types, - }; -} - -// returns true if x is equal to y and false otherwise. Performs some minimal -// type conversion and data massaging for x and y, depending on type. name and -// type should typically be derived from parseEthersParams. -function isAbiDataEqual(name: ParamName, type: string, x: any, y: any): boolean { - if (_.isUndefined(x) && _.isUndefined(y)) { - return true; - } else if (_.isUndefined(x) && !_.isUndefined(y)) { - return false; - } else if (!_.isUndefined(x) && _.isUndefined(y)) { - return false; - } - if (_.endsWith(type, '[]')) { - // For array types, we iterate through the elements and check each one - // individually. Strangely, name does not need to be changed in this - // case. - if (x.length !== y.length) { - return false; - } - const newType = _.trimEnd(type, '[]'); - for (let i = 0; i < x.length; i++) { - if (!isAbiDataEqual(name, newType, x[i], y[i])) { - return false; - } - } - return true; - } - if (_.startsWith(type, 'tuple(')) { - if (_.isString(name)) { - throw new Error('Internal error: type was tuple but names was a string'); - } else if (_.isNull(name)) { - throw new Error('Internal error: type was tuple but names was null'); - } - // For tuples, we iterate through the underlying values and check each - // one individually. - const types = splitTupleTypes(type); - if (types.length !== name.names.length) { - throw new Error( - `Internal error: parameter types/names length mismatch (${types.length} != ${name.names.length})`, - ); - } - for (let i = 0; i < types.length; i++) { - // For tuples, name is an object with a names property that is an - // array. As an example, for orders, name looks like: - // - // { - // name: 'orders', - // names: [ - // 'makerAddress', - // // ... - // 'takerAssetData' - // ] - // } - // - const nestedName = _.isString(name.names[i]) - ? (name.names[i] as string) - : ((name.names[i] as NestedParamName).name as string); - if (!isAbiDataEqual(name.names[i], types[i], x[nestedName], y[nestedName])) { - return false; - } - } - return true; - } else if (type === 'address' || type === 'bytes') { - // HACK(albrow): ethers.js returns the checksummed address even when - // initially passed in a non-checksummed address. To account for that, - // we convert to lowercase before comparing. - return _.isEqual(_.toLower(x), _.toLower(y)); - } else if (_.startsWith(type, 'uint') || _.startsWith(type, 'int')) { - return new BigNumber(x).eq(new BigNumber(y)); - } - return _.isEqual(x, y); -} - -// splitTupleTypes splits a tuple type string (of the form `tuple(X)` where X is -// any other type or list of types) into its component types. It works with -// nested tuples, so, e.g., `tuple(tuple(uint256,address),bytes32)` will yield: -// `['tuple(uint256,address)', 'bytes32']`. It expects exactly one tuple type as -// an argument (not an array). -function splitTupleTypes(type: string): string[] { - if (_.endsWith(type, '[]')) { - throw new Error('Internal error: array types are not supported'); - } else if (!_.startsWith(type, 'tuple(')) { - throw new Error(`Internal error: expected tuple type but got non-tuple type: ${type}`); - } - // Trim the outtermost tuple(). - const trimmedType = type.substring('tuple('.length, type.length - 1); - const types: string[] = []; - let currToken = ''; - let parenCount = 0; - // Tokenize the type string while keeping track of parentheses. - for (const char of trimmedType) { - switch (char) { - case '(': - parenCount += 1; - currToken += char; - break; - case ')': - parenCount -= 1; - currToken += char; - break; - case ',': - if (parenCount === 0) { - types.push(currToken); - currToken = ''; - break; - } else { - currToken += char; - break; - } - default: - currToken += char; - break; - } - } - types.push(currToken); - return types; -} - -export const abiUtils = { - parseEthersParams, - isAbiDataEqual, - splitTupleTypes, - parseFunctionParam(param: DataItem): string { - if (param.type === 'tuple') { - // Parse out tuple types into {type_1, type_2, ..., type_N} - const tupleComponents = param.components; - const paramString = _.map(tupleComponents, component => abiUtils.parseFunctionParam(component)); - const tupleParamString = `{${paramString}}`; - return tupleParamString; - } - return param.type; - }, - getFunctionSignature(methodAbi: MethodAbi): string { - const functionName = methodAbi.name; - const parameterTypeList = _.map(methodAbi.inputs, (param: DataItem) => abiUtils.parseFunctionParam(param)); - const functionSignature = `${functionName}(${parameterTypeList})`; - return functionSignature; - }, - /** - * Solidity supports function overloading whereas TypeScript does not. - * See: https://solidity.readthedocs.io/en/v0.4.21/contracts.html?highlight=overload#function-overloading - * In order to support overloaded functions, we suffix overloaded function names with an index. - * This index should be deterministic, regardless of function ordering within the smart contract. To do so, - * we assign indexes based on the alphabetical order of function signatures. - * - * E.g - * ['f(uint)', 'f(uint,byte32)'] - * Should always be renamed to: - * ['f1(uint)', 'f2(uint,byte32)'] - * Regardless of the order in which these these overloaded functions are declared within the contract ABI. - */ - renameOverloadedMethods(inputContractAbi: ContractAbi): ContractAbi { - const contractAbi = _.cloneDeep(inputContractAbi); - const methodAbis = contractAbi.filter((abi: AbiDefinition) => abi.type === AbiType.Function) as MethodAbi[]; - // Sort method Abis into alphabetical order, by function signature - const methodAbisOrdered = _.sortBy(methodAbis, [ - (methodAbi: MethodAbi) => { - const functionSignature = abiUtils.getFunctionSignature(methodAbi); - return functionSignature; - }, - ]); - // Group method Abis by name (overloaded methods will be grouped together, in alphabetical order) - const methodAbisByName: { [key: string]: MethodAbi[] } = {}; - _.each(methodAbisOrdered, methodAbi => { - (methodAbisByName[methodAbi.name] || (methodAbisByName[methodAbi.name] = [])).push(methodAbi); - }); - // Rename overloaded methods to overloadedMethodName1, overloadedMethodName2, ... - _.each(methodAbisByName, methodAbisWithSameName => { - _.each(methodAbisWithSameName, (methodAbi, i: number) => { - if (methodAbisWithSameName.length > 1) { - const overloadedMethodId = i + 1; - const sanitizedMethodName = `${methodAbi.name}${overloadedMethodId}`; - const indexOfExistingAbiWithSanitizedMethodNameIfExists = _.findIndex( - methodAbis, - currentMethodAbi => currentMethodAbi.name === sanitizedMethodName, - ); - if (indexOfExistingAbiWithSanitizedMethodNameIfExists >= 0) { - const methodName = methodAbi.name; - throw new Error( - `Failed to rename overloaded method '${methodName}' to '${sanitizedMethodName}'. A method with this name already exists.`, - ); - } - methodAbi.name = sanitizedMethodName; - } - }); - }); - return contractAbi; - }, -}; diff --git a/packages/utils/src/address_utils.ts b/packages/utils/src/address_utils.ts deleted file mode 100644 index 1fc960408..000000000 --- a/packages/utils/src/address_utils.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { addHexPrefix, stripHexPrefix } from 'ethereumjs-util'; -import * as jsSHA3 from 'js-sha3'; -import * as _ from 'lodash'; - -const BASIC_ADDRESS_REGEX = /^(0x)?[0-9a-f]{40}$/i; -const SAME_CASE_ADDRESS_REGEX = /^(0x)?([0-9a-f]{40}|[0-9A-F]{40})$/; -const ADDRESS_LENGTH = 40; - -export const addressUtils = { - isChecksumAddress(address: string): boolean { - // Check each case - const unprefixedAddress = address.replace('0x', ''); - const addressHash = jsSHA3.keccak256(unprefixedAddress.toLowerCase()); - - for (let i = 0; i < ADDRESS_LENGTH; i++) { - // The nth letter should be uppercase if the nth digit of casemap is 1 - const hexBase = 16; - const lowercaseRange = 7; - if ( - (parseInt(addressHash[i], hexBase) > lowercaseRange && - unprefixedAddress[i].toUpperCase() !== unprefixedAddress[i]) || - (parseInt(addressHash[i], hexBase) <= lowercaseRange && - unprefixedAddress[i].toLowerCase() !== unprefixedAddress[i]) - ) { - return false; - } - } - return true; - }, - isAddress(address: string): boolean { - if (!BASIC_ADDRESS_REGEX.test(address)) { - // Check if it has the basic requirements of an address - return false; - } else if (SAME_CASE_ADDRESS_REGEX.test(address)) { - // If it's all small caps or all all caps, return true - return true; - } else { - // Otherwise check each case - const isValidChecksummedAddress = addressUtils.isChecksumAddress(address); - return isValidChecksummedAddress; - } - }, - padZeros(address: string): string { - return addHexPrefix(_.padStart(stripHexPrefix(address), ADDRESS_LENGTH, '0')); - }, -}; diff --git a/packages/utils/src/class_utils.ts b/packages/utils/src/class_utils.ts deleted file mode 100644 index 04e60ee57..000000000 --- a/packages/utils/src/class_utils.ts +++ /dev/null @@ -1,18 +0,0 @@ -import * as _ from 'lodash'; - -export const classUtils = { - // This is useful for classes that have nested methods. Nested methods don't get bound out of the box. - bindAll(self: any, exclude: string[] = ['contructor'], thisArg?: any): void { - for (const key of Object.getOwnPropertyNames(self)) { - const val = self[key]; - if (!_.includes(exclude, key)) { - if (_.isFunction(val)) { - self[key] = val.bind(thisArg || self); - } else if (_.isObject(val)) { - classUtils.bindAll(val, exclude, self); - } - } - } - return self; - }, -}; diff --git a/packages/utils/src/configured_bignumber.ts b/packages/utils/src/configured_bignumber.ts deleted file mode 100644 index 34b57d303..000000000 --- a/packages/utils/src/configured_bignumber.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { BigNumber } from 'bignumber.js'; - -BigNumber.config({ - // By default BigNumber's `toString` method converts to exponential notation if the value has - // more then 20 digits. We want to avoid this behavior, so we set EXPONENTIAL_AT to a high number - EXPONENTIAL_AT: 1000, - // Note(albrow): This is the lowest value for which - // `x.div(y).floor() === x.divToInt(y)` - // for all values of x and y <= MAX_UINT256, where MAX_UINT256 is the - // maximum number represented by the uint256 type in Solidity (2^256-1). - DECIMAL_PLACES: 78, -}); - -// Set a debug print function for NodeJS -// Upstream issue: https://github.com/MikeMcl/bignumber.js/issues/188 -import isNode = require('detect-node'); -if (isNode) { - // Dynamically load a NodeJS specific module. - // Typescript requires all imports to be global, so we need to use - // `const` here and disable the tslint warning. - // tslint:disable-next-line: no-var-requires - const util = require('util'); - - // Set a custom util.inspect function - // HACK: We add a function to the BigNumber class by assigning to the - // prototype. The function name is a symbol provided by Node. - (BigNumber.prototype as any)[util.inspect.custom] = function(): string { - // HACK: When executed, `this` will refer to the BigNumber instance. - // This is also why we need a function expression instead of an - // arrow function, as the latter does not have a `this`. - // Return the readable string representation - // tslint:disable-next-line: no-invalid-this - return this.toString(); - }; -} - -export { BigNumber }; diff --git a/packages/utils/src/constants.ts b/packages/utils/src/constants.ts deleted file mode 100644 index 2894d4747..000000000 --- a/packages/utils/src/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const NULL_BYTES = '0x'; diff --git a/packages/utils/src/error_utils.ts b/packages/utils/src/error_utils.ts deleted file mode 100644 index 735d3940b..000000000 --- a/packages/utils/src/error_utils.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const errorUtils = { - spawnSwitchErr(name: string, value: any): Error { - return new Error(`Unexpected switch value: ${value} encountered for ${name}`); - }, -}; diff --git a/packages/utils/src/fetch_async.ts b/packages/utils/src/fetch_async.ts deleted file mode 100644 index b4c85718d..000000000 --- a/packages/utils/src/fetch_async.ts +++ /dev/null @@ -1,40 +0,0 @@ -import isNode = require('detect-node'); -import 'isomorphic-fetch'; -// WARNING: This needs to be imported after isomorphic-fetch: https://github.com/mo/abortcontroller-polyfill#using-it-on-browsers-without-fetch -// tslint:disable-next-line:ordered-imports -import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'; - -export const fetchAsync = async ( - endpoint: string, - options: RequestInit = {}, - timeoutMs: number = 20000, -): Promise<Response> => { - if (options.signal || (options as any).timeout) { - throw new Error( - 'Cannot call fetchAsync with options.signal or options.timeout. To set a timeout, please use the supplied "timeoutMs" parameter.', - ); - } - let optionsWithAbortParam; - if (!isNode) { - const controller = new AbortController(); - const signal = controller.signal; - setTimeout(() => { - controller.abort(); - }, timeoutMs); - optionsWithAbortParam = { - signal, - ...options, - }; - } else { - // HACK: the `timeout` param only exists in `node-fetch`, and not on the `isomorphic-fetch` - // `RequestInit` type. Since `isomorphic-fetch` conditionally wraps `node-fetch` when the - // execution environment is `Node.js`, we need to cast it to `any` in that scenario. - optionsWithAbortParam = { - timeout: timeoutMs, - ...options, - } as any; - } - - const response = await fetch(endpoint, optionsWithAbortParam); - return response; -}; diff --git a/packages/utils/src/globals.d.ts b/packages/utils/src/globals.d.ts deleted file mode 100644 index 94e63a32d..000000000 --- a/packages/utils/src/globals.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module '*.json' { - const json: any; - /* tslint:disable */ - export default json; - /* tslint:enable */ -} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts deleted file mode 100644 index 082aff6bb..000000000 --- a/packages/utils/src/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export { promisify } from './promisify'; -export { addressUtils } from './address_utils'; -export { classUtils } from './class_utils'; -export { intervalUtils } from './interval_utils'; -export { BigNumber } from './configured_bignumber'; -export { AbiDecoder } from './abi_decoder'; -export { logUtils } from './log_utils'; -export { abiUtils } from './abi_utils'; -export { NULL_BYTES } from './constants'; -export { errorUtils } from './error_utils'; -export { fetchAsync } from './fetch_async'; -export { signTypedDataUtils } from './sign_typed_data_utils'; -export import AbiEncoder = require('./abi_encoder'); diff --git a/packages/utils/src/interval_utils.ts b/packages/utils/src/interval_utils.ts deleted file mode 100644 index 3d0561cd2..000000000 --- a/packages/utils/src/interval_utils.ts +++ /dev/null @@ -1,39 +0,0 @@ -export const intervalUtils = { - setAsyncExcludingInterval( - fn: () => Promise<void>, - intervalMs: number, - onError: (err: Error) => void, - ): NodeJS.Timer { - let isLocked = false; - const intervalId = setInterval(async () => { - if (isLocked) { - return; - } else { - isLocked = true; - try { - await fn(); - } catch (err) { - onError(err); - } - isLocked = false; - } - }, intervalMs); - return intervalId; - }, - clearAsyncExcludingInterval(intervalId: NodeJS.Timer): void { - clearInterval(intervalId); - }, - setInterval(fn: () => void, intervalMs: number, onError: (err: Error) => void): NodeJS.Timer { - const intervalId = setInterval(() => { - try { - fn(); - } catch (err) { - onError(err); - } - }, intervalMs); - return intervalId; - }, - clearInterval(intervalId: NodeJS.Timer): void { - clearInterval(intervalId); - }, -}; diff --git a/packages/utils/src/log_utils.ts b/packages/utils/src/log_utils.ts deleted file mode 100644 index 6d9996c67..000000000 --- a/packages/utils/src/log_utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -import chalk from 'chalk'; - -export const logUtils = { - log(...args: any[]): void { - console.log(...args); // tslint:disable-line:no-console - }, - warn(...args: any[]): void { - console.warn(...args); // tslint:disable-line:no-console - }, - logWithTime(arg: string): void { - logUtils.log(`[${chalk.gray(new Date().toLocaleTimeString())}] ${arg}`); - }, -}; diff --git a/packages/utils/src/promisify.ts b/packages/utils/src/promisify.ts deleted file mode 100644 index e82251a0f..000000000 --- a/packages/utils/src/promisify.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as _ from 'lodash'; - -/** - * Transforms callback-based function -- func(arg1, arg2 .. argN, callback) -- into an ES6-compatible Promise. - * Promisify provides a default callback of the form (error, result) and rejects when `error` is not null. You can also - * supply thisArg object as the second argument which will be passed to `apply`. - */ -// HACK: This can't be properly typed without variadic kinds https://github.com/Microsoft/TypeScript/issues/5453 -export function promisify<T>(originalFn: (...args: any[]) => void, thisArg?: any): (...callArgs: any[]) => Promise<T> { - const promisifiedFunction = async (...callArgs: any[]): Promise<T> => { - return new Promise<T>((resolve, reject) => { - const callback = (err: Error | null, data?: T) => { - _.isNull(err) || _.isUndefined(err) ? resolve(data) : reject(err); - }; - originalFn.apply(thisArg, [...callArgs, callback]); - }); - }; - return promisifiedFunction; -} diff --git a/packages/utils/src/sign_typed_data_utils.ts b/packages/utils/src/sign_typed_data_utils.ts deleted file mode 100644 index adb66622d..000000000 --- a/packages/utils/src/sign_typed_data_utils.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { EIP712Object, EIP712ObjectValue, EIP712TypedData, EIP712Types } from '@0x/types'; -import * as ethUtil from 'ethereumjs-util'; -import * as ethers from 'ethers'; -import * as _ from 'lodash'; - -import { BigNumber } from './configured_bignumber'; - -export const signTypedDataUtils = { - /** - * Generates the EIP712 Typed Data hash for signing - * @param typedData An object that conforms to the EIP712TypedData interface - * @return A Buffer containing the hash of the typed data. - */ - generateTypedDataHash(typedData: EIP712TypedData): Buffer { - return ethUtil.sha3( - Buffer.concat([ - Buffer.from('1901', 'hex'), - signTypedDataUtils._structHash('EIP712Domain', typedData.domain, typedData.types), - signTypedDataUtils._structHash(typedData.primaryType, typedData.message, typedData.types), - ]), - ); - }, - _findDependencies(primaryType: string, types: EIP712Types, found: string[] = []): string[] { - if (found.includes(primaryType) || types[primaryType] === undefined) { - return found; - } - found.push(primaryType); - for (const field of types[primaryType]) { - for (const dep of signTypedDataUtils._findDependencies(field.type, types, found)) { - if (!found.includes(dep)) { - found.push(dep); - } - } - } - return found; - }, - _encodeType(primaryType: string, types: EIP712Types): string { - let deps = signTypedDataUtils._findDependencies(primaryType, types); - deps = deps.filter(d => d !== primaryType); - deps = [primaryType].concat(deps.sort()); - let result = ''; - for (const dep of deps) { - result += `${dep}(${types[dep].map(({ name, type }) => `${type} ${name}`).join(',')})`; - } - return result; - }, - _encodeData(primaryType: string, data: EIP712Object, types: EIP712Types): string { - const encodedTypes = ['bytes32']; - const encodedValues: Array<Buffer | EIP712ObjectValue> = [signTypedDataUtils._typeHash(primaryType, types)]; - for (const field of types[primaryType]) { - const value = data[field.name]; - if (field.type === 'string' || field.type === 'bytes') { - const hashValue = ethUtil.sha3(value as string); - encodedTypes.push('bytes32'); - encodedValues.push(hashValue); - } else if (types[field.type] !== undefined) { - encodedTypes.push('bytes32'); - const hashValue = ethUtil.sha3( - // tslint:disable-next-line:no-unnecessary-type-assertion - signTypedDataUtils._encodeData(field.type, value as EIP712Object, types), - ); - encodedValues.push(hashValue); - } else if (field.type.lastIndexOf(']') === field.type.length - 1) { - throw new Error('Arrays currently unimplemented in encodeData'); - } else { - encodedTypes.push(field.type); - const normalizedValue = signTypedDataUtils._normalizeValue(field.type, value); - encodedValues.push(normalizedValue); - } - } - return ethers.utils.defaultAbiCoder.encode(encodedTypes, encodedValues); - }, - _normalizeValue(type: string, value: any): EIP712ObjectValue { - const normalizedValue = type === 'uint256' && BigNumber.isBigNumber(value) ? value.toString() : value; - return normalizedValue; - }, - _typeHash(primaryType: string, types: EIP712Types): Buffer { - return ethUtil.sha3(signTypedDataUtils._encodeType(primaryType, types)); - }, - _structHash(primaryType: string, data: EIP712Object, types: EIP712Types): Buffer { - return ethUtil.sha3(signTypedDataUtils._encodeData(primaryType, data, types)); - }, -}; diff --git a/packages/utils/test/abi_encoder/abi_samples/method_abis.ts b/packages/utils/test/abi_encoder/abi_samples/method_abis.ts deleted file mode 100644 index fc552c127..000000000 --- a/packages/utils/test/abi_encoder/abi_samples/method_abis.ts +++ /dev/null @@ -1,780 +0,0 @@ -/* tslint:disable max-file-line-count */ -import { MethodAbi } from 'ethereum-types'; - -export const simpleAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'greg', - type: 'uint256', - }, - { - name: 'gregStr', - type: 'string', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const stringAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'greg', - type: 'string[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const GAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'a', - type: 'uint256', - }, - { - name: 'b', - type: 'string', - }, - { - name: 'e', - type: 'bytes', - }, - { - name: 'f', - type: 'address', - }, - ], - - name: 'f', - type: 'tuple', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const typesWithDefaultWidthsAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'someUint', - type: 'uint', - }, - { - name: 'someInt', - type: 'int', - }, - { - name: 'someByte', - type: 'byte', - }, - { - name: 'someUint', - type: 'uint[]', - }, - { - name: 'someInt', - type: 'int[]', - }, - { - name: 'someByte', - type: 'byte[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const multiDimensionalArraysStaticTypeAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'a', - type: 'uint8[][][]', - }, - { - name: 'b', - type: 'uint8[][][2]', - }, - { - name: 'c', - type: 'uint8[][2][]', - }, - { - name: 'd', - type: 'uint8[2][][]', - }, - { - name: 'e', - type: 'uint8[][2][2]', - }, - { - name: 'f', - type: 'uint8[2][2][]', - }, - { - name: 'g', - type: 'uint8[2][][2]', - }, - { - name: 'h', - type: 'uint8[2][2][2]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const multiDimensionalArraysDynamicTypeAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'a', - type: 'string[][][]', - }, - { - name: 'b', - type: 'string[][][2]', - }, - { - name: 'c', - type: 'string[][2][]', - }, - { - name: 'h', - type: 'string[2][2][2]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const dynamicTupleAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someStr', - type: 'string', - }, - ], - name: 'order', - type: 'tuple', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const arrayOfStaticTuplesWithDefinedLengthAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someUint2', - type: 'uint256', - }, - ], - name: 'order', - type: 'tuple[8]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const arrayOfStaticTuplesWithDynamicLengthAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someUint2', - type: 'uint256', - }, - ], - name: 'order', - type: 'tuple[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const arrayOfDynamicTuplesWithDefinedLengthAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someString', - type: 'string', - }, - ], - name: 'order', - type: 'tuple[8]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const arrayOfDynamicTuplesWithUndefinedLengthAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someString', - type: 'string', - }, - ], - name: 'order', - type: 'tuple[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const arrayOfDynamicTuplesAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someString', - type: 'string', - }, - ], - name: 'order', - type: 'tuple[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const multidimensionalArrayOfDynamicTuplesAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someString', - type: 'string', - }, - ], - name: 'order', - type: 'tuple[][2][]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const staticTupleAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'someUint1', - type: 'uint256', - }, - { - name: 'someUint2', - type: 'uint256', - }, - { - name: 'someUint3', - type: 'uint256', - }, - { - name: 'someBool', - type: 'bool', - }, - ], - name: 'order', - type: 'tuple', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const staticArrayAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'someStaticArray', - type: 'uint8[3]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const staticArrayDynamicMembersAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'someStaticArray', - type: 'string[3]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const dynamicArrayDynamicMembersAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'someStaticArray', - type: 'string[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const dynamicArrayStaticMembersAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'someStaticArray', - type: 'uint8[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const largeFlatAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'someUInt256', - type: 'uint256', - }, - { - name: 'someInt256', - type: 'int256', - }, - { - name: 'someInt32', - type: 'int32', - }, - { - name: 'someByte', - type: 'byte', - }, - { - name: 'someBytes32', - type: 'bytes32', - }, - { - name: 'someBytes', - type: 'bytes', - }, - { - name: 'someString', - type: 'string', - }, - { - name: 'someAddress', - type: 'address', - }, - { - name: 'someBool', - type: 'bool', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const largeNestedAbi: MethodAbi = { - constant: false, - inputs: [ - { - name: 'someStaticArray', - type: 'uint8[3]', - }, - { - name: 'someStaticArrayWithDynamicMembers', - type: 'string[2]', - }, - { - name: 'someDynamicArrayWithDynamicMembers', - type: 'bytes[]', - }, - { - name: 'some2DArray', - type: 'string[][]', - }, - { - name: 'someTuple', - type: 'tuple', - components: [ - { - name: 'someUint32', - type: 'uint32', - }, - { - name: 'someStr', - type: 'string', - }, - ], - }, - { - name: 'someTupleWithDynamicTypes', - type: 'tuple', - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someStr', - type: 'string', - }, - /*{ - name: 'someStrArray', - type: 'string[]', - },*/ - { - name: 'someBytes', - type: 'bytes', - }, - { - name: 'someAddress', - type: 'address', - }, - ], - }, - { - name: 'someArrayOfTuplesWithDynamicTypes', - type: 'tuple[]', - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someStr', - type: 'string', - }, - /*{ - name: 'someStrArray', - type: 'string[]', - },*/ - { - name: 'someBytes', - type: 'bytes', - }, - { - name: 'someAddress', - type: 'address', - }, - ], - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const nestedTuples: MethodAbi = { - constant: false, - inputs: [ - { - name: 'firstTuple', - type: 'tuple[1]', - components: [ - { - name: 'someUint32', - type: 'uint32', - }, - { - name: 'nestedTuple', - type: 'tuple', - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someAddress', - type: 'address', - }, - ], - }, - ], - }, - { - name: 'secondTuple', - type: 'tuple[]', - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someStr', - type: 'string', - }, - { - name: 'nestedTuple', - type: 'tuple', - components: [ - { - name: 'someUint32', - type: 'uint32', - }, - { - name: 'secondNestedTuple', - type: 'tuple', - components: [ - { - name: 'someUint', - type: 'uint256', - }, - { - name: 'someStr', - type: 'string', - }, - { - name: 'someBytes', - type: 'bytes', - }, - { - name: 'someAddress', - type: 'address', - }, - ], - }, - ], - }, - { - name: 'someBytes', - type: 'bytes', - }, - { - name: 'someAddress', - type: 'address', - }, - ], - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const simpleAbi2: MethodAbi = { - constant: false, - inputs: [ - { - name: 'someByte', - type: 'byte', - }, - { - name: 'someBytes32', - type: 'bytes32', - }, - { - name: 'someBytes', - type: 'bytes', - }, - { - name: 'someString', - type: 'string', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const fillOrderAbi: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'makerAddress', - type: 'address', - }, - { - name: 'takerAddress', - type: 'address', - }, - { - name: 'feeRecipientAddress', - type: 'address', - }, - { - name: 'senderAddress', - type: 'address', - }, - { - name: 'makerAssetAmount', - type: 'uint256', - }, - { - name: 'takerAssetAmount', - type: 'uint256', - }, - { - name: 'makerFee', - type: 'uint256', - }, - { - name: 'takerFee', - type: 'uint256', - }, - { - name: 'expirationTimeSeconds', - type: 'uint256', - }, - { - name: 'salt', - type: 'uint256', - }, - { - name: 'makerAssetData', - type: 'bytes', - }, - { - name: 'takerAssetData', - type: 'bytes', - }, - ], - name: 'order', - type: 'tuple', - }, - { - name: 'takerAssetFillAmount', - type: 'uint256', - }, - { - name: 'salt', - type: 'uint256', - }, - { - name: 'orderSignature', - type: 'bytes', - }, - { - name: 'takerSignature', - type: 'bytes', - }, - ], - name: 'fillOrder', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; diff --git a/packages/utils/test/abi_encoder/abi_samples/optimizer_abis.ts b/packages/utils/test/abi_encoder/abi_samples/optimizer_abis.ts deleted file mode 100644 index 7cfd7a118..000000000 --- a/packages/utils/test/abi_encoder/abi_samples/optimizer_abis.ts +++ /dev/null @@ -1,340 +0,0 @@ -/* tslint:disable max-file-line-count */ -import { MethodAbi } from 'ethereum-types'; - -export const duplicateDynamicArraysWithStaticElements: MethodAbi = { - constant: false, - inputs: [ - { - name: 'array1', - type: 'uint[]', - }, - { - name: 'array2', - type: 'uint[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateDynamicArraysWithDynamicElements: MethodAbi = { - constant: false, - inputs: [ - { - name: 'array1', - type: 'string[]', - }, - { - name: 'array2', - type: 'string[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateStaticArraysWithStaticElements: MethodAbi = { - constant: false, - inputs: [ - { - name: 'array1', - type: 'uint[2]', - }, - { - name: 'array2', - type: 'uint[2]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateStaticArraysWithDynamicElements: MethodAbi = { - constant: false, - inputs: [ - { - name: 'array1', - type: 'string[2]', - }, - { - name: 'array2', - type: 'string[2]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateArrayElements: MethodAbi = { - constant: false, - inputs: [ - { - name: 'array', - type: 'string[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateTupleFields: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'field1', - type: 'string', - }, - { - name: 'field2', - type: 'string', - }, - ], - name: 'Tuple', - type: 'tuple', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateStrings: MethodAbi = { - constant: false, - inputs: [ - { - name: 'string1', - type: 'string', - }, - { - name: 'string2', - type: 'string', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateBytes: MethodAbi = { - constant: false, - inputs: [ - { - name: 'bytes1', - type: 'bytes', - }, - { - name: 'bytes2', - type: 'bytes', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateTuples: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'field1', - type: 'string', - }, - { - name: 'field2', - type: 'uint', - }, - ], - name: 'Tuple', - type: 'tuple', - }, - { - components: [ - { - name: 'field1', - type: 'string', - }, - { - name: 'field2', - type: 'uint', - }, - ], - name: 'Tuple', - type: 'tuple', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateArraysNestedInTuples: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - name: 'field', - type: 'uint[]', - }, - ], - name: 'Tuple1', - type: 'tuple', - }, - { - components: [ - { - name: 'field', - type: 'uint[]', - }, - { - name: 'extraField', - type: 'string', - }, - ], - name: 'Tuple2', - type: 'tuple', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateTuplesNestedInTuples: MethodAbi = { - constant: false, - inputs: [ - { - components: [ - { - components: [ - { - name: 'nestedField', - type: 'string', - }, - ], - name: 'field', - type: 'tuple', - }, - ], - name: 'Tuple1', - type: 'tuple', - }, - { - components: [ - { - components: [ - { - name: 'nestedField', - type: 'string', - }, - ], - name: 'field', - type: 'tuple', - }, - { - name: 'extraField', - type: 'string', - }, - ], - name: 'Tuple1', - type: 'tuple', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const duplicateTwoDimensionalArrays: MethodAbi = { - constant: false, - inputs: [ - { - name: 'array1', - type: 'string[][]', - }, - { - name: 'array2', - type: 'string[][]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const arrayElementsDuplicatedAsSeparateParameter: MethodAbi = { - constant: false, - inputs: [ - { - name: 'stringArray', - type: 'string[]', - }, - { - name: 'string', - type: 'string', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const arrayElementsDuplicatedAsTupleFields: MethodAbi = { - constant: false, - inputs: [ - { - name: 'uint8Array', - type: 'uint8[]', - }, - { - components: [ - { - name: 'uint', - type: 'uint', - }, - ], - name: 'uintTuple', - type: 'tuple[]', - }, - ], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; diff --git a/packages/utils/test/abi_encoder/abi_samples/return_value_abis.ts b/packages/utils/test/abi_encoder/abi_samples/return_value_abis.ts deleted file mode 100644 index ac2124011..000000000 --- a/packages/utils/test/abi_encoder/abi_samples/return_value_abis.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* tslint:disable max-file-line-count */ -import { MethodAbi } from 'ethereum-types'; - -export const noReturnValues: MethodAbi = { - constant: false, - inputs: [], - name: 'simpleFunction', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const singleStaticReturnValue: MethodAbi = { - constant: false, - inputs: [], - name: 'simpleFunction', - outputs: [ - { - name: 'Bytes4', - type: 'bytes4', - }, - ], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const multipleStaticReturnValues: MethodAbi = { - constant: false, - inputs: [], - name: 'simpleFunction', - outputs: [ - { - name: 'val1', - type: 'bytes4', - }, - { - name: 'val2', - type: 'bytes4', - }, - ], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const singleDynamicReturnValue: MethodAbi = { - constant: false, - inputs: [], - name: 'simpleFunction', - outputs: [ - { - name: 'val', - type: 'bytes', - }, - ], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const multipleDynamicReturnValues: MethodAbi = { - constant: false, - inputs: [], - name: 'simpleFunction', - outputs: [ - { - name: 'val1', - type: 'bytes', - }, - { - name: 'val2', - type: 'bytes', - }, - ], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; - -export const mixedStaticAndDynamicReturnValues: MethodAbi = { - constant: false, - inputs: [], - name: 'simpleFunction', - outputs: [ - { - name: 'val1', - type: 'bytes4', - }, - { - name: 'val2', - type: 'bytes', - }, - ], - payable: false, - stateMutability: 'nonpayable', - type: 'function', -}; diff --git a/packages/utils/test/abi_encoder/evm_data_types_test.ts b/packages/utils/test/abi_encoder/evm_data_types_test.ts deleted file mode 100644 index 4814ce28b..000000000 --- a/packages/utils/test/abi_encoder/evm_data_types_test.ts +++ /dev/null @@ -1,1168 +0,0 @@ -/* tslint:disable max-file-line-count */ -import * as chai from 'chai'; -import * as ethUtil from 'ethereumjs-util'; -import 'mocha'; - -import { AbiEncoder, BigNumber } from '../../src/'; -import { chaiSetup } from '../utils/chai_setup'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('ABI Encoder: EVM Data Type Encoding/Decoding', () => { - const encodingRules: AbiEncoder.EncodingRules = { shouldOptimize: false }; // optimizer is tested separately. - describe('Array', () => { - it('Fixed size; Static elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'int[2]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const args = [new BigNumber(5), new BigNumber(6)]; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Dynamic size; Static elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'int[]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const args = [new BigNumber(5), new BigNumber(6)]; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Fixed size; Dynamic elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'string[2]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const args = ['Hello', 'world']; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005776f726c64000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Dynamic size; Dynamic elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'string[]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const args = ['Hello', 'world']; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005776f726c64000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Dynamic Size; Multidimensional; Dynamic Elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'bytes[][]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const array1 = ['0x01020304', '0x05060708', '0x09101112']; - const array2 = ['0x10111213', '0x14151617']; - const array3 = ['0x18192021']; - const args = [array1, array2, array3]; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000405060708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004091011120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000041011121300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000414151617000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000041819202100000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Dynamic Size; Multidimensional; Static Elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'bytes4[][]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const array1 = ['0x01020304', '0x05060708', '0x09101112']; - const array2 = ['0x10111213', '0x14151617']; - const array3 = ['0x18192021']; - const args = [array1, array2, array3]; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x0000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000301020304000000000000000000000000000000000000000000000000000000000506070800000000000000000000000000000000000000000000000000000000091011120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021011121300000000000000000000000000000000000000000000000000000000141516170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011819202100000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Static Size; Multidimensional; Static Elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'bytes4[3][2]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const array1 = ['0x01020304', '0x05060708', '0x09101112']; - const array2 = ['0x10111213', '0x14151617', '0x18192021']; - const args = [array1, array2]; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x010203040000000000000000000000000000000000000000000000000000000005060708000000000000000000000000000000000000000000000000000000000910111200000000000000000000000000000000000000000000000000000000101112130000000000000000000000000000000000000000000000000000000014151617000000000000000000000000000000000000000000000000000000001819202100000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Static Size; Multidimensional; Dynamic Elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'bytes[3][2]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const array1 = ['0x01020304', '0x05060708', '0x09101112']; - const array2 = ['0x10111213', '0x14151617', '0x18192021']; - const args = [array1, array2]; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000401020304000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004050607080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040910111200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000410111213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004141516170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041819202100000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Static size; Too Few Elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'string[3]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const args = ['Hello', 'world']; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw('Expected array of 3 elements, but got array of length 2'); - }); - it('Static size; Too Many Elements', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'string[1]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const args = ['Hello', 'world']; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw('Expected array of 1 elements, but got array of length 2'); - }); - it('Element Type Mismatch', async () => { - // Create DataType object - const testDataItem = { name: 'testArray', type: 'uint[]' }; - const dataType = new AbiEncoder.Array(testDataItem); - // Construct args to be encoded - const args = [new BigNumber(1), 'Bad Argument']; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw('Tried to assign NaN value'); - }); - }); - - describe('Tuple', () => { - it('Static elements only', async () => { - // Create DataType object - const testDataItem = { - name: 'Tuple', - type: 'tuple', - components: [{ name: 'field_1', type: 'int32' }, { name: 'field_2', type: 'bool' }], - }; - const dataType = new AbiEncoder.Tuple(testDataItem); - // Construct args to be encoded - const args = { field_1: new BigNumber(-5), field_2: true }; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0000000000000000000000000000000000000000000000000000000000000001'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true }; - const decodedArgs = dataType.decode(encodedArgs, decodingRules); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args, encodingRules); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Dynamic elements only', async () => { - // Create DataType object - const testDataItem = { - name: 'Tuple', - type: 'tuple', - components: [{ name: 'field_1', type: 'string' }, { name: 'field_2', type: 'bytes' }], - }; - const dataType = new AbiEncoder.Tuple(testDataItem); - // Construct args to be encoded - const args = { field_1: 'Hello, World!', field_2: '0xabcdef0123456789' }; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20576f726c6421000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008abcdef0123456789000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true }; - const decodedArgs = dataType.decode(encodedArgs, decodingRules); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Nested Static Array', async () => { - // Create DataType object - const testDataItem = { - name: 'Tuple', - type: 'tuple', - components: [{ name: 'field', type: 'uint[2]' }], - }; - const dataType = new AbiEncoder.Tuple(testDataItem); - // Construct args to be encoded - const args = { field: [new BigNumber(1), new BigNumber(2)] }; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true }; - const decodedArgs = dataType.decode(encodedArgs, decodingRules); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Nested Dynamic Array', async () => { - // Create DataType object - const testDataItem = { - name: 'Tuple', - type: 'tuple', - components: [{ name: 'field', type: 'uint[]' }], - }; - const dataType = new AbiEncoder.Tuple(testDataItem); - // Construct args to be encoded - const args = { field: [new BigNumber(1), new BigNumber(2)] }; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true }; - const decodedArgs = dataType.decode(encodedArgs, decodingRules); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Nested Static Multidimensional Array', async () => { - // Create DataType object - const testDataItem = { - name: 'Tuple', - type: 'tuple', - components: [{ name: 'field', type: 'bytes4[2][2]' }], - }; - const dataType = new AbiEncoder.Tuple(testDataItem); - // Construct args to be encoded - const array1 = ['0x01020304', '0x05060708']; - const array2 = ['0x09101112', '0x13141516']; - const args = { field: [array1, array2] }; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x0102030400000000000000000000000000000000000000000000000000000000050607080000000000000000000000000000000000000000000000000000000009101112000000000000000000000000000000000000000000000000000000001314151600000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true }; - const decodedArgs = dataType.decode(encodedArgs, decodingRules); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Nested Dynamic Multidimensional Array', async () => { - // Create DataType object - const testDataItem = { - name: 'Tuple', - type: 'tuple', - components: [{ name: 'field', type: 'bytes[2][2]' }], - }; - const dataType = new AbiEncoder.Tuple(testDataItem); - // Construct args to be encoded - const array1 = ['0x01020304', '0x05060708']; - const array2 = ['0x09101112', '0x13141516']; - const args = { field: [array1, array2] }; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004010203040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040506070800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004091011120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041314151600000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true }; - const decodedArgs = dataType.decode(encodedArgs, decodingRules); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Static and dynamic elements mixed', async () => { - // Create DataType object - const testDataItem = { - name: 'Tuple', - type: 'tuple', - components: [ - { name: 'field_1', type: 'int32' }, - { name: 'field_2', type: 'string' }, - { name: 'field_3', type: 'bool' }, - { name: 'field_4', type: 'bytes' }, - ], - }; - const dataType = new AbiEncoder.Tuple(testDataItem); - // Construct args to be encoded - const args = { - field_1: new BigNumber(-5), - field_2: 'Hello, World!', - field_3: true, - field_4: '0xabcdef0123456789', - }; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20576f726c6421000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008abcdef0123456789000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodingRules: AbiEncoder.DecodingRules = { shouldConvertStructsToObjects: true }; - const decodedArgs = dataType.decode(encodedArgs, decodingRules); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Missing Key', async () => { - // Create DataType object - const testDataItem = { - name: 'Tuple', - type: 'tuple', - components: [{ name: 'field_1', type: 'int32' }, { name: 'field_2', type: 'bool' }], - }; - const dataType = new AbiEncoder.Tuple(testDataItem); - // Construct args to be encoded - const args = { field_1: new BigNumber(-5) }; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw('Could not assign tuple to object: missing key \'field_2\' in object {"field_1":"-5"}'); - }); - }); - - describe('Address', () => { - it('Valid Address', async () => { - // Create DataType object - const testDataItem = { name: 'Address', type: 'address' }; - const dataType = new AbiEncoder.Address(testDataItem); - // Construct args to be encoded - const args = '0xe41d2489571d322189246dafa5ebde1f4699f498'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Invalid Address - input is not valid hex', async () => { - // Create DataType object - const testDataItem = { name: 'Address', type: 'address' }; - const dataType = new AbiEncoder.Address(testDataItem); - // Construct args to be encoded - const args = 'e4'; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(`Invalid address: '${args}'`); - }); - it('Invalid Address - input is not 20 bytes', async () => { - // Create DataType object - const testDataItem = { name: 'Address', type: 'address' }; - const dataType = new AbiEncoder.Address(testDataItem); - // Construct args to be encoded - const args = '0xe4'; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(`Invalid address: '${args}'`); - }); - }); - - describe('Bool', () => { - it('True', async () => { - // Create DataType object - const testDataItem = { name: 'Boolean', type: 'bool' }; - const dataType = new AbiEncoder.Bool(testDataItem); - // Construct args to be encoded - const args = true; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0000000000000000000000000000000000000000000000000000000000000001'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('False', async () => { - // Create DataType object - const testDataItem = { name: 'Boolean', type: 'bool' }; - const dataType = new AbiEncoder.Bool(testDataItem); - // Construct args to be encoded - const args = false; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0000000000000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - }); - - describe('Integer', () => { - /* tslint:disable custom-no-magic-numbers */ - const max256BitInteger = new BigNumber(2).pow(255).minus(1); - const min256BitInteger = new BigNumber(2).pow(255).times(-1); - const max32BitInteger = new BigNumber(2).pow(31).minus(1); - const min32BitInteger = new BigNumber(2).pow(31).times(-1); - /* tslint:enable custom-no-magic-numbers */ - - it('Int256 - Positive Base Case', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (256)', type: 'int' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = new BigNumber(1); - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0000000000000000000000000000000000000000000000000000000000000001'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Int256 - Negative Base Case', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (256)', type: 'int' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = new BigNumber(-1); - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Int256 - Positive Value', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (256)', type: 'int' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = max256BitInteger; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Int256 - Negative Value', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (256)', type: 'int' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = min256BitInteger; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = `0x8000000000000000000000000000000000000000000000000000000000000000`; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Int256 - Value too large', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (256)', type: 'int' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = max256BitInteger.plus(1); - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(); - }); - it('Int256 - Value too small', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (256)', type: 'int' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = min256BitInteger.minus(1); - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(); - }); - it('Int32 - Positive Base Case', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (32)', type: 'int32' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = new BigNumber(1); - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0000000000000000000000000000000000000000000000000000000000000001'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Int32 - Negative Base Case', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (32)', type: 'int32' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = new BigNumber(-1); - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Int32 - Positive Value', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (32)', type: 'int32' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = max32BitInteger; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x000000000000000000000000000000000000000000000000000000007fffffff'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Int32 - Negative Value', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (32)', type: 'int32' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = min32BitInteger; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000`; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Int32 - Value too large', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (32)', type: 'int32' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = max32BitInteger.plus(1); - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(); - }); - it('Int32 - Value too small', async () => { - // Create DataType object - const testDataItem = { name: 'Integer (32)', type: 'int32' }; - const dataType = new AbiEncoder.Int(testDataItem); - // Construct args to be encoded - const args = min32BitInteger.minus(1); - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(); - }); - }); - - describe('Unsigned Integer', () => { - /* tslint:disable custom-no-magic-numbers */ - const max256BitUnsignedInteger = new BigNumber(2).pow(256).minus(1); - const min256BitUnsignedInteger = new BigNumber(0); - const max32BitUnsignedInteger = new BigNumber(2).pow(32).minus(1); - const min32BitUnsignedInteger = new BigNumber(0); - /* tslint:enable custom-no-magic-numbers */ - - it('UInt256 - Positive Base Case', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (256)', type: 'uint' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = new BigNumber(1); - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0000000000000000000000000000000000000000000000000000000000000001'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('UInt256 - Positive Value', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (256)', type: 'uint' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = max256BitUnsignedInteger; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('UInt256 - Zero Value', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (256)', type: 'uint' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = min256BitUnsignedInteger; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = `0x0000000000000000000000000000000000000000000000000000000000000000`; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('UInt256 - Value too large', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (256)', type: 'uint' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = max256BitUnsignedInteger.plus(1); - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(); - }); - it('UInt256 - Value too small', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (256)', type: 'uint' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = min256BitUnsignedInteger.minus(1); - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(); - }); - it('UInt32 - Positive Base Case', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (32)', type: 'uint32' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = new BigNumber(1); - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0000000000000000000000000000000000000000000000000000000000000001'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('UInt32 - Positive Value', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (32)', type: 'uint32' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = max32BitUnsignedInteger; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x00000000000000000000000000000000000000000000000000000000ffffffff'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('UInt32 - Zero Value', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (32)', type: 'uint32' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = min32BitUnsignedInteger; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = `0x0000000000000000000000000000000000000000000000000000000000000000`; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('UInt32 - Value too large', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (32)', type: 'uint32' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = max32BitUnsignedInteger.plus(1); - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(); - }); - it('UInt32 - Value too small', async () => { - // Create DataType object - const testDataItem = { name: 'Unsigned Integer (32)', type: 'uint32' }; - const dataType = new AbiEncoder.UInt(testDataItem); - // Construct args to be encoded - const args = min32BitUnsignedInteger.minus(1); - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw(); - }); - }); - - describe('Static Bytes', () => { - it('Single Byte (byte)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Byte', type: 'byte' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - const args = '0x05'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0500000000000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Single Byte (bytes1)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes1', type: 'bytes1' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - const args = '0x05'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0500000000000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('4 Bytes (bytes4)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes4', type: 'bytes4' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - const args = '0x00010203'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0001020300000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('4 Bytes (bytes4); Encoder must pad input', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes4', type: 'bytes4' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - // Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes. - const args = '0x1a18'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x1a18000000000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - const paddedArgs = '0x1a180000'; - expect(decodedArgs).to.be.deep.equal(paddedArgs); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('32 Bytes (bytes32)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes32', type: 'bytes32' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - const args = '0x0001020304050607080911121314151617181920212223242526272829303132'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x0001020304050607080911121314151617181920212223242526272829303132'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('32 Bytes (bytes32); Encoder must pad input', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes32', type: 'bytes32' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - // Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes. - const args = '0x1a18bf61'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = '0x1a18bf6100000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - const paddedArgs = '0x1a18bf6100000000000000000000000000000000000000000000000000000000'; - expect(decodedArgs).to.be.deep.equal(paddedArgs); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Should throw when pass in too many bytes (bytes4)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes4', type: 'bytes4' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - const args = '0x0102030405'; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw( - 'Tried to assign 0x0102030405 (5 bytes), which exceeds max bytes that can be stored in a bytes4', - ); - }); - it('Should throw when pass in too many bytes (bytes32)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes32', type: 'bytes32' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - const args = '0x010203040506070809101112131415161718192021222324252627282930313233'; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw( - 'Tried to assign 0x010203040506070809101112131415161718192021222324252627282930313233 (33 bytes), which exceeds max bytes that can be stored in a bytes32', - ); - }); - it('Should throw when pass in bad hex (no 0x prefix)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes32', type: 'bytes32' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - const args = '0102030405060708091011121314151617181920212223242526272829303132'; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw("Tried to encode non-hex value. Value must inlcude '0x' prefix."); - }); - it('Should throw when pass in bad hex (include a half-byte)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes32', type: 'bytes32' }; - const dataType = new AbiEncoder.StaticBytes(testDataItem); - // Construct args to be encoded - const args = '0x010'; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw('Tried to assign 0x010, which is contains a half-byte. Use full bytes only.'); - }); - }); - - describe('Dynamic Bytes', () => { - it('Fits into one EVM word', async () => { - // Create DataType object - const testDataItem = { name: 'Dynamic Bytes', type: 'bytes' }; - const dataType = new AbiEncoder.DynamicBytes(testDataItem); - // Construct args to be encoded - // Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes. - const args = '0x1a18bf61'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x00000000000000000000000000000000000000000000000000000000000000041a18bf6100000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Spans multiple EVM words', async () => { - // Create DataType object - const testDataItem = { name: 'Dynamic Bytes', type: 'bytes' }; - const dataType = new AbiEncoder.DynamicBytes(testDataItem); - // Construct args to be encoded - // Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes. - const bytesLength = 40; - const args = `0x${'61'.repeat(bytesLength)}`; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x000000000000000000000000000000000000000000000000000000000000002861616161616161616161616161616161616161616161616161616161616161616161616161616161000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Input as Buffer', async () => { - // Create DataType object - const testDataItem = { name: 'Dynamic Bytes', type: 'bytes' }; - const dataType = new AbiEncoder.DynamicBytes(testDataItem); - // Construct args to be encoded - // Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes. - const args = '0x1a18bf61'; - const argsAsBuffer = ethUtil.toBuffer(args); - // Encode Args and validate result - const encodedArgs = dataType.encode(argsAsBuffer); - const expectedEncodedArgs = - '0x00000000000000000000000000000000000000000000000000000000000000041a18bf6100000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Should throw when pass in bad hex (no 0x prefix)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes', type: 'bytes' }; - const dataType = new AbiEncoder.DynamicBytes(testDataItem); - // Construct args to be encoded - const args = '01'; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw("Tried to encode non-hex value. Value must inlcude '0x' prefix."); - }); - it('Should throw when pass in bad hex (include a half-byte)', async () => { - // Create DataType object - const testDataItem = { name: 'Static Bytes', type: 'bytes' }; - const dataType = new AbiEncoder.DynamicBytes(testDataItem); - // Construct args to be encoded - const args = '0x010'; - // Encode Args and validate result - expect(() => { - dataType.encode(args, encodingRules); - }).to.throw('Tried to assign 0x010, which is contains a half-byte. Use full bytes only.'); - }); - }); - - describe('String', () => { - it('Fits into one EVM word', async () => { - // Create DataType object - const testDataItem = { name: 'String', type: 'string' }; - const dataType = new AbiEncoder.String(testDataItem); - // Construct args to be encoded - // Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes. - const args = 'five'; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x00000000000000000000000000000000000000000000000000000000000000046669766500000000000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('Spans multiple EVM words', async () => { - // Create DataType object - const testDataItem = { name: 'String', type: 'string' }; - const dataType = new AbiEncoder.String(testDataItem); - // Construct args to be encoded - // Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes. - const bytesLength = 40; - const args = 'a'.repeat(bytesLength); - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x000000000000000000000000000000000000000000000000000000000000002861616161616161616161616161616161616161616161616161616161616161616161616161616161000000000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - it('String that begins with 0x prefix', async () => { - // Create DataType object - const testDataItem = { name: 'String', type: 'string' }; - const dataType = new AbiEncoder.String(testDataItem); - // Construct args to be encoded - // Note: There will be padding because this is a bytes32 but we are only passing in 4 bytes. - const strLength = 40; - const args = `0x${'a'.repeat(strLength)}`; - // Encode Args and validate result - const encodedArgs = dataType.encode(args, encodingRules); - const expectedEncodedArgs = - '0x000000000000000000000000000000000000000000000000000000000000002a30786161616161616161616161616161616161616161616161616161616161616161616161616161616100000000000000000000000000000000000000000000'; - expect(encodedArgs).to.be.equal(expectedEncodedArgs); - // Decode Encoded Args and validate result - const decodedArgs = dataType.decode(encodedArgs); - expect(decodedArgs).to.be.deep.equal(args); - // Validate signature - const dataTypeFromSignature = AbiEncoder.create(dataType.getSignature(true)); - const argsEncodedFromSignature = dataTypeFromSignature.encode(args); - expect(argsEncodedFromSignature).to.be.deep.equal(expectedEncodedArgs); - }); - }); -}); diff --git a/packages/utils/test/abi_encoder/methods_test.ts b/packages/utils/test/abi_encoder/methods_test.ts deleted file mode 100644 index d8045fece..000000000 --- a/packages/utils/test/abi_encoder/methods_test.ts +++ /dev/null @@ -1,385 +0,0 @@ -import * as chai from 'chai'; -import 'mocha'; - -import { AbiEncoder, BigNumber } from '../../src/'; -import { chaiSetup } from '../utils/chai_setup'; - -import * as AbiSamples from './abi_samples/method_abis'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('ABI Encoder: Method Encoding / Decoding', () => { - const encodingRules: AbiEncoder.EncodingRules = { shouldOptimize: false }; // optimizer is tested separately. - it('Types with default widths', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.typesWithDefaultWidthsAbi); - const args = [new BigNumber(1), new BigNumber(-1), '0x56', [new BigNumber(1)], [new BigNumber(-1)], ['0x56']]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x09f2b0c30000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000015600000000000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Array of Static Tuples (Array has defined length)', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.arrayOfStaticTuplesWithDefinedLengthAbi); - let value = 0; - const arrayOfTuples = []; - const arrayOfTuplesLength = 8; - for (let i = 0; i < arrayOfTuplesLength; ++i) { - arrayOfTuples.push([new BigNumber(++value), new BigNumber(++value)]); - } - const args = [arrayOfTuples]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x9eb20969000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Array of Static Tuples (Array has dynamic length)', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.arrayOfStaticTuplesWithDynamicLengthAbi); - let value = 0; - const arrayOfTuples = []; - const arrayOfTuplesLength = 8; - for (let i = 0; i < arrayOfTuplesLength; ++i) { - arrayOfTuples.push([new BigNumber(++value), new BigNumber(++value)]); - } - const args = [arrayOfTuples]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x63275d6e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Array of Dynamic Tuples (Array has defined length)', async () => { - // Generate Calldata - const method = new AbiEncoder.Method(AbiSamples.arrayOfDynamicTuplesWithDefinedLengthAbi); - let value = 0; - const arrayOfTuples = []; - const arrayOfTuplesLength = 8; - for (let i = 0; i < arrayOfTuplesLength; ++i) { - arrayOfTuples.push([new BigNumber(++value), new BigNumber(++value).toString()]); - } - const args = [arrayOfTuples]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0xdeedb00f00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000132000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000013400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000138000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000023130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000023132000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000023134000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000023136000000000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Array of Dynamic Tuples (Array has dynamic length)', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.arrayOfDynamicTuplesWithUndefinedLengthAbi); - let value = 0; - const arrayOfTuples = []; - const arrayOfTuplesLength = 8; - for (let i = 0; i < arrayOfTuplesLength; ++i) { - arrayOfTuples.push([new BigNumber(++value), new BigNumber(++value).toString()]); - } - const args = [arrayOfTuples]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x60c847fb000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000132000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000013400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000138000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000023130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000023132000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000023134000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000023136000000000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Multidimensional Arrays / Static Members', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.multiDimensionalArraysStaticTypeAbi); - // Eight 3-dimensional arrays of uint8[2][2][2] - let value = 0; - const args = []; - const argsLength = 8; - for (let i = 0; i < argsLength; ++i) { - args.push([[[++value, ++value], [++value, ++value]], [[++value, ++value], [++value, ++value]]]); - } - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0xc2f47d6f00000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000d400000000000000000000000000000000000000000000000000000000000000e600000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000130000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000019000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000025000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000027000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000029000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002f0000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003600000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000038'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Multidimensional Arrays / Dynamic Members', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.multiDimensionalArraysDynamicTypeAbi); - // Eight 3-dimensional arrays of string[2][2][2] - let value = 0; - const args = []; - const argsLength = 4; - for (let i = 0; i < argsLength; ++i) { - args.push([ - [ - [new BigNumber(++value).toString(), new BigNumber(++value).toString()], - [new BigNumber(++value).toString(), new BigNumber(++value).toString()], - ], - [ - [new BigNumber(++value).toString(), new BigNumber(++value).toString()], - [new BigNumber(++value).toString(), new BigNumber(++value).toString()], - ], - ]); - } - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x81534ebd0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000131000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000013300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000134000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000137000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000139000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002313000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000023131000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000231320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000002313300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000023134000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000231350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002313600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000231370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002313800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000023139000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000232300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000023231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000232320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000002323300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000023234000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000232350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002323600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000232370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002323800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000002323900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000023330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000002333100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000023332000000000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Fixed Length Array / Dynamic Members', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.staticArrayDynamicMembersAbi); - const args = [['Brave', 'New', 'World']]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x243a6e6e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000005427261766500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034e657700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c64000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Fixed Length Array / Dynamic Members', async () => { - // Generaet calldata - const method = new AbiEncoder.Method(AbiSamples.staticArrayDynamicMembersAbi); - const args = [['Brave', 'New', 'World']]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x243a6e6e0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000005427261766500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034e657700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c64000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Unfixed Length Array / Dynamic Members ABI', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.dynamicArrayDynamicMembersAbi); - const args = [['Brave', 'New', 'World']]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x13e751a900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000005427261766500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034e657700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c64000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Unfixed Length Array / Static Members ABI', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.dynamicArrayStaticMembersAbi); - // tslint:disable custom-no-magic-numbers - const args = [[127, 14, 54]]; - // tslint:enable custom-no-magic-numbers - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x4fc8a83300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000036'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Fixed Length Array / Static Members ABI', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.staticArrayAbi); - // tslint:disable custom-no-magic-numbers - const args = [[127, 14, 54]]; - // tslint:enable custom-no-magic-numbers - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0xf68ade72000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000036'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Array ABI', async () => { - // Generate calldata - const method = new AbiEncoder.Method(AbiSamples.stringAbi); - const args = [['five', 'six', 'seven']]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x13e751a900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000046669766500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000373697800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005736576656e000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Static Tuple', async () => { - // Generate calldata - // This is dynamic because it has dynamic members - const method = new AbiEncoder.Method(AbiSamples.staticTupleAbi); - const args = [[new BigNumber(5), new BigNumber(10), new BigNumber(15), false]]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0xa9125e150000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000f0000000000000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Dynamic Tuple (Array input)', async () => { - // Generate calldata - // This is dynamic because it has dynamic members - const method = new AbiEncoder.Method(AbiSamples.dynamicTupleAbi); - const args = [[new BigNumber(5), 'five']]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x5b998f3500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000046669766500000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Dynamic Tuple (Object input)', async () => { - // Generate Calldata - // This is dynamic because it has dynamic members - const method = new AbiEncoder.Method(AbiSamples.dynamicTupleAbi); - const args = [[new BigNumber(5), 'five']]; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x5b998f3500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000046669766500000000000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Large, Flat ABI', async () => { - // Construct calldata - const method = new AbiEncoder.Method(AbiSamples.largeFlatAbi); - const args = [ - new BigNumber(256745454), - new BigNumber(-256745454), - new BigNumber(434244), - '0x43', - '0x0001020304050607080911121314151617181920212223242526272829303132', - '0x0001020304050607080911121314151617181920212223242526272829303132080911121314151617181920212223242526272829303132', - 'Little peter piper piped a piping pepper pot', - '0xe41d2489571d322189246dafa5ebde1f4699f498', - true, - ]; - // Validate calldata - const calldata = method.encode(args, encodingRules); - const expectedCalldata = - '0x312d4d42000000000000000000000000000000000000000000000000000000000f4d9feefffffffffffffffffffffffffffffffffffffffffffffffffffffffff0b26012000000000000000000000000000000000000000000000000000000000006a0444300000000000000000000000000000000000000000000000000000000000000000102030405060708091112131415161718192021222324252627282930313200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000180000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f4980000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000003800010203040506070809111213141516171819202122232425262728293031320809111213141516171819202122232425262728293031320000000000000000000000000000000000000000000000000000000000000000000000000000002c4c6974746c65207065746572207069706572207069706564206120706970696e672070657070657220706f740000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodingRules = { shouldConvertStructsToObjects: false }; - const decodedValue = method.decode(calldata, decodingRules); - expect(decodedValue).to.be.deep.equal(args); - }); - it('Large, Nested ABI', async () => { - // Construct Calldata - const method = new AbiEncoder.Method(AbiSamples.largeNestedAbi); - // tslint:disable custom-no-magic-numbers - const someStaticArray = [127, 14, 54]; - // tslint:enable custom-no-magic-numbers - const someStaticArrayWithDynamicMembers = [ - 'the little piping piper piped a piping pipper papper', - 'the kid knows how to write poems, what can I say -- I guess theres a lot I could say to try to fill this line with a lot of text.', - ]; - const someDynamicArrayWithDynamicMembers = [ - '0x38745637834987324827439287423897238947239847', - '0x7283472398237423984723984729847248927498748974284728947239487498749847874329423743492347329847239842374892374892374892347238947289478947489374289472894738942749823743298742389472389473289472389437249823749823742893472398', - '0x283473298473248923749238742398742398472894729843278942374982374892374892743982', - ]; - const some2DArray = [ - [ - 'some string', - 'some another string', - 'there are just too many stringsup in', - 'here', - 'yall ghonna make me lose my mind', - ], - [ - 'the little piping piper piped a piping pipper papper', - 'the kid knows how to write poems, what can I say -- I guess theres a lot I could say to try to fill this line with a lot of text.', - ], - [], - ]; - const someTuple = { - someUint32: new BigNumber(4037824789), - someStr: - 'the kid knows how to write poems, what can I say -- I guess theres a lot I could say to try to fill this line with a lot of text.', - }; - const someTupleWithDynamicTypes = { - someUint: new BigNumber(4024789), - someStr: 'akdhjasjkdhasjkldshdjahdkjsahdajksdhsajkdhsajkdhadjkashdjksadhajkdhsajkdhsadjk', - someBytes: '0x29384723894723843743289742389472398473289472348927489274894738427428947389facdea', - someAddress: '0xe41d2489571d322189246dafa5ebde1f4699f498', - }; - const someTupleWithDynamicTypes2 = { - someUint: new BigNumber(9024789), - someStr: 'ksdhsajkdhsajkdhadjkashdjksadhajkdhsajkdhsadjkakdhjasjkdhasjkldshdjahdkjsahdaj', - someBytes: '0x29384723894398473289472348927489272384374328974238947274894738427428947389facde1', - someAddress: '0x746dafa5ebde1f4699f4981d3221892e41d24895', - }; - const someTupleWithDynamicTypes3 = { - someUint: new BigNumber(1024789), - someStr: 'sdhsajkdhsajkdhadjkashdjakdhjasjkdhasjkldshdjahdkjsahdajkksadhajkdhsajkdhsadjk', - someBytes: '0x38947238437432829384729742389472398473289472348927489274894738427428947389facdef', - someAddress: '0x89571d322189e415ebde1f4699f498d24246dafa', - }; - const someArrayOfTuplesWithDynamicTypes = [someTupleWithDynamicTypes2, someTupleWithDynamicTypes3]; - const args = { - someStaticArray, - someStaticArrayWithDynamicMembers, - someDynamicArrayWithDynamicMembers, - some2DArray, - someTuple, - someTupleWithDynamicTypes, - someArrayOfTuplesWithDynamicTypes, - }; - const calldata = method.encode(args, encodingRules); - // Validate calldata - const expectedCalldata = - '0x4b49031c000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000009800000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000034746865206c6974746c6520706970696e67207069706572207069706564206120706970696e6720706970706572207061707065720000000000000000000000000000000000000000000000000000000000000000000000000000000000000081746865206b6964206b6e6f777320686f7720746f20777269746520706f656d732c20776861742063616e204920736179202d2d2049206775657373207468657265732061206c6f74204920636f756c642073617920746f2074727920746f2066696c6c2074686973206c696e6520776974682061206c6f74206f6620746578742e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000163874563783498732482743928742389723894723984700000000000000000000000000000000000000000000000000000000000000000000000000000000006e72834723982374239847239847298472489274987489742847289472394874987498478743294237434923473298472398423748923748923748923472389472894789474893742894728947389427498237432987423894723894732894723894372498237498237428934723980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027283473298473248923749238742398742398472894729843278942374982374892374892743982000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000b736f6d6520737472696e670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013736f6d6520616e6f7468657220737472696e67000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024746865726520617265206a75737420746f6f206d616e7920737472696e6773757020696e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046865726500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002079616c6c2067686f6e6e61206d616b65206d65206c6f7365206d79206d696e640000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000034746865206c6974746c6520706970696e67207069706572207069706564206120706970696e6720706970706572207061707065720000000000000000000000000000000000000000000000000000000000000000000000000000000000000081746865206b6964206b6e6f777320686f7720746f20777269746520706f656d732c20776861742063616e204920736179202d2d2049206775657373207468657265732061206c6f74204920636f756c642073617920746f2074727920746f2066696c6c2074686973206c696e6520776974682061206c6f74206f6620746578742e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0ac511500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000081746865206b6964206b6e6f777320686f7720746f20777269746520706f656d732c20776861742063616e204920736179202d2d2049206775657373207468657265732061206c6f74204920636f756c642073617920746f2074727920746f2066696c6c2074686973206c696e6520776974682061206c6f74206f6620746578742e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003d69d500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498000000000000000000000000000000000000000000000000000000000000004e616b64686a61736a6b646861736a6b6c647368646a6168646b6a73616864616a6b73646873616a6b646873616a6b646861646a6b617368646a6b73616468616a6b646873616a6b64687361646a6b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002829384723894723843743289742389472398473289472348927489274894738427428947389facdea0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000089b51500000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000746dafa5ebde1f4699f4981d3221892e41d24895000000000000000000000000000000000000000000000000000000000000004e6b73646873616a6b646873616a6b646861646a6b617368646a6b73616468616a6b646873616a6b64687361646a6b616b64686a61736a6b646861736a6b6c647368646a6168646b6a73616864616a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002829384723894398473289472348927489272384374328974238947274894738427428947389facde100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa3150000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000089571d322189e415ebde1f4699f498d24246dafa000000000000000000000000000000000000000000000000000000000000004e73646873616a6b646873616a6b646861646a6b617368646a616b64686a61736a6b646861736a6b6c647368646a6168646b6a73616864616a6b6b73616468616a6b646873616a6b64687361646a6b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002838947238437432829384729742389472398473289472348927489274894738427428947389facdef000000000000000000000000000000000000000000000000'; - expect(calldata).to.be.equal(expectedCalldata); - // Validate decoding - const decodedValue = method.decode(calldata, { shouldConvertStructsToObjects: true }); - expect(decodedValue).to.be.deep.equal(args); - }); -}); diff --git a/packages/utils/test/abi_encoder/optimizer_test.ts b/packages/utils/test/abi_encoder/optimizer_test.ts deleted file mode 100644 index c2881f14c..000000000 --- a/packages/utils/test/abi_encoder/optimizer_test.ts +++ /dev/null @@ -1,269 +0,0 @@ -import * as chai from 'chai'; -import 'mocha'; - -import { AbiEncoder, BigNumber } from '../../src/'; -import { chaiSetup } from '../utils/chai_setup'; - -import * as OptimizedAbis from './abi_samples/optimizer_abis'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('ABI Encoder: Optimized Method Encoding/Decoding', () => { - const encodingRules: AbiEncoder.EncodingRules = { shouldOptimize: true }; - it('Duplicate Dynamic Arrays with Static Elements', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateDynamicArraysWithStaticElements); - const array1 = [new BigNumber(100), new BigNumber(150)]; - const array2 = array1; - const args = [array1, array2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x7221063300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000096'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Dynamic Arrays with Dynamic Elements', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateDynamicArraysWithDynamicElements); - const array1 = ['Hello', 'World']; - const array2 = array1; - const args = [array1, array2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0xbb4f12e300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c64000000000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Static Arrays with Static Elements (should not optimize)', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateStaticArraysWithStaticElements); - const array1 = [new BigNumber(100), new BigNumber(150)]; - const array2 = array1; - const args = [array1, array2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x7f8130430000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000096'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - const unoptimizedCalldata = method.encode(args); - expect(optimizedCalldata).to.be.equal(unoptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Static Arrays with Dynamic Elements', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateStaticArraysWithDynamicElements); - const array1 = ['Hello', 'World']; - const array2 = array1; - const args = [array1, array2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x9fe31f8e0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c64000000000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Array Elements (should optimize)', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateArrayElements); - const strings = ['Hello', 'World', 'Hello', 'World']; - const args = [strings]; - // Validate calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x13e751a900000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c64000000000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Tuple Fields', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateTupleFields); - const tuple = ['Hello', 'Hello']; - const args = [tuple]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x16780a5e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Strings', async () => { - // Description: - // Two dynamic arrays with the same values. - // In the optimized calldata, only one set of elements should be included. - // Both arrays should point to this set. - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateStrings); - const args = ['Hello', 'Hello']; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x07370bfa00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Bytes', async () => { - // Description: - // Two dynamic arrays with the same values. - // In the optimized calldata, only one set of elements should be included. - // Both arrays should point to this set. - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateBytes); - const value = '0x01020304050607080910111213141516171819202122232425262728293031323334353637383940'; - const args = [value, value]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x6045e42900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002801020304050607080910111213141516171819202122232425262728293031323334353637383940000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Tuples', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateTuples); - const tuple1 = ['Hello, World!', new BigNumber(424234)]; - const tuple2 = tuple1; - const args = [tuple1, tuple2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x564f826d000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000006792a000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20576f726c642100000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Fields Across Two Tuples', async () => { - // Description: - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateTuples); - const tuple1 = ['Hello, World!', new BigNumber(1)]; - const tuple2 = [tuple1[0], new BigNumber(2)]; - const args = [tuple1, tuple2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x564f826d000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20576f726c642100000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Arrays, Nested in Separate Tuples', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateArraysNestedInTuples); - const array = [new BigNumber(100), new BigNumber(150), new BigNumber(200)]; - const tuple1 = [array]; - const tuple2 = [array, 'extra argument to prevent exactly matching the tuples']; - const args = [tuple1, tuple2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x18970a9e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c80000000000000000000000000000000000000000000000000000000000000035657874726120617267756d656e7420746f2070726576656e742065786163746c79206d61746368696e6720746865207475706c65730000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Tuples, Nested in Separate Tuples', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateTuplesNestedInTuples); - const nestedTuple = ['Hello, World!']; - const tuple1 = [nestedTuple]; - const tuple2 = [nestedTuple, 'extra argument to prevent exactly matching the tuples']; - const args = [tuple1, tuple2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x0b4d2e6a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20576f726c6421000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035657874726120617267756d656e7420746f2070726576656e742065786163746c79206d61746368696e6720746865207475706c65730000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Two-Dimensional Arrays', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateTwoDimensionalArrays); - const twoDimArray1 = [['Hello', 'World'], ['Foo', 'Bar', 'Zaa']]; - const twoDimArray2 = twoDimArray1; - const args = [twoDimArray1, twoDimArray2]; - // Validata calldata - const optimizedCalldata = method.encode(args, { shouldOptimize: false }); - const expectedOptimizedCalldata = - '0x0d28c4f9000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003466f6f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003426172000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a61610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000003466f6f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003426172000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a61610000000000000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Duplicate Array, Nested within Separate Two-Dimensional Arrays', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.duplicateTwoDimensionalArrays); - const twoDimArray1 = [['Hello', 'World'], ['Foo']]; - const twoDimArray2 = [['Hello', 'World'], ['Bar']]; - const args = [twoDimArray1, twoDimArray2]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x0d28c4f900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003466f6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000548656c6c6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005576f726c640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000034261720000000000000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Array Elements Duplicated as Tuple Fields', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.arrayElementsDuplicatedAsTupleFields); - // tslint:disable custom-no-magic-numbers - const array = [100, 150, 200, 225]; - // tslint:enable custom-no-magic-numbers - const tuple = [ - [new BigNumber(array[0])], - [new BigNumber(array[1])], - [new BigNumber(array[2])], - [new BigNumber(array[3])], - ]; - const args = [array, tuple]; - // Validata calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0x5b5c78fd0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000009600000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000e1'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); - it('Array Elements Duplicated as Separate Parameter', async () => { - // Generate calldata - const method = new AbiEncoder.Method(OptimizedAbis.arrayElementsDuplicatedAsSeparateParameter); - const array = ['Hello', 'Hello', 'Hello', 'World']; - const str = 'Hello'; - const args = [array, str]; - // Validate calldata - const optimizedCalldata = method.encode(args, encodingRules); - const expectedOptimizedCalldata = - '0xe0e0d34900000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000005576f726c64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000548656c6c6f000000000000000000000000000000000000000000000000000000'; - expect(optimizedCalldata).to.be.equal(expectedOptimizedCalldata); - // Validate decoding - const decodedArgs = method.decode(optimizedCalldata, { shouldConvertStructsToObjects: false }); - expect(decodedArgs).to.be.deep.equal(args); - }); -}); diff --git a/packages/utils/test/abi_encoder/return_values_test.ts b/packages/utils/test/abi_encoder/return_values_test.ts deleted file mode 100644 index 308d11ee5..000000000 --- a/packages/utils/test/abi_encoder/return_values_test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as chai from 'chai'; -import 'mocha'; - -import { AbiEncoder } from '../../src/'; -import { chaiSetup } from '../utils/chai_setup'; - -import * as ReturnValueAbis from './abi_samples/return_value_abis'; - -chaiSetup.configure(); -const expect = chai.expect; - -describe('ABI Encoder: Return Value Encoding/Decoding', () => { - const encodingRules: AbiEncoder.EncodingRules = { shouldOptimize: false }; // optimizer is tested separately. - it('No Return Value', async () => { - // Decode return value - const method = new AbiEncoder.Method(ReturnValueAbis.noReturnValues); - const returnValue = '0x'; - const decodedReturnValue = method.decodeReturnValues(returnValue, { shouldConvertStructsToObjects: false }); - const expectedDecodedReturnValue: any[] = []; - expect(decodedReturnValue).to.be.deep.equal(expectedDecodedReturnValue); - }); - it('Single static return value', async () => { - // Generate Return Value - const method = new AbiEncoder.Method(ReturnValueAbis.singleStaticReturnValue); - const returnValue = ['0x01020304']; - const encodedReturnValue = method.encodeReturnValues(returnValue, encodingRules); - const decodedReturnValue = method.decodeReturnValues(encodedReturnValue, { - shouldConvertStructsToObjects: false, - }); - // Validate decoded return value - expect(decodedReturnValue).to.be.deep.equal(returnValue); - }); - it('Multiple static return values', async () => { - // Generate Return Value - const method = new AbiEncoder.Method(ReturnValueAbis.multipleStaticReturnValues); - const returnValue = ['0x01020304', '0x05060708']; - const encodedReturnValue = method.encodeReturnValues(returnValue, encodingRules); - const decodedReturnValue = method.decodeReturnValues(encodedReturnValue, { - shouldConvertStructsToObjects: false, - }); - // Validate decoded return value - expect(decodedReturnValue).to.be.deep.equal(returnValue); - }); - it('Single dynamic return value', async () => { - // Generate Return Value - const method = new AbiEncoder.Method(ReturnValueAbis.singleDynamicReturnValue); - const returnValue = ['0x01020304']; - const encodedReturnValue = method.encodeReturnValues(returnValue, encodingRules); - const decodedReturnValue = method.decodeReturnValues(encodedReturnValue, { - shouldConvertStructsToObjects: false, - }); - // Validate decoded return value - expect(decodedReturnValue).to.be.deep.equal(returnValue); - }); - it('Multiple dynamic return values', async () => { - // Generate Return Value - const method = new AbiEncoder.Method(ReturnValueAbis.multipleDynamicReturnValues); - const returnValue = ['0x01020304', '0x05060708']; - const encodedReturnValue = method.encodeReturnValues(returnValue, encodingRules); - const decodedReturnValue = method.decodeReturnValues(encodedReturnValue, { - shouldConvertStructsToObjects: false, - }); - // Validate decoded return value - expect(decodedReturnValue).to.be.deep.equal(returnValue); - }); - it('Mixed static/dynamic return values', async () => { - // Generate Return Value - const method = new AbiEncoder.Method(ReturnValueAbis.mixedStaticAndDynamicReturnValues); - const returnValue = ['0x01020304', '0x05060708']; - const encodedReturnValue = method.encodeReturnValues(returnValue, encodingRules); - const decodedReturnValue = method.decodeReturnValues(encodedReturnValue, { - shouldConvertStructsToObjects: false, - }); - // Validate decoded return value - expect(decodedReturnValue).to.be.deep.equal(returnValue); - }); -}); diff --git a/packages/utils/test/abi_encoder/signature_tests.ts b/packages/utils/test/abi_encoder/signature_tests.ts deleted file mode 100644 index e69de29bb..000000000 --- a/packages/utils/test/abi_encoder/signature_tests.ts +++ /dev/null diff --git a/packages/utils/test/abi_utils_test.ts b/packages/utils/test/abi_utils_test.ts deleted file mode 100644 index 0ebee64c4..000000000 --- a/packages/utils/test/abi_utils_test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as chai from 'chai'; -import 'mocha'; - -import { abiUtils } from '../src'; - -const expect = chai.expect; - -describe('abiUtils', () => { - describe('splitTupleTypes', () => { - it('handles basic types', () => { - const got = abiUtils.splitTupleTypes('tuple(bytes,uint256,address)'); - expect(got).to.deep.equal(['bytes', 'uint256', 'address']); - }); - it('handles nested tuple types', () => { - const got = abiUtils.splitTupleTypes('tuple(tuple(bytes,uint256),address)'); - expect(got).to.deep.equal(['tuple(bytes,uint256)', 'address']); - }); - }); -}); diff --git a/packages/utils/test/sign_typed_data_utils_test.ts b/packages/utils/test/sign_typed_data_utils_test.ts deleted file mode 100644 index 3d2cb2496..000000000 --- a/packages/utils/test/sign_typed_data_utils_test.ts +++ /dev/null @@ -1,163 +0,0 @@ -import * as chai from 'chai'; -import 'mocha'; - -import { signTypedDataUtils } from '../src/sign_typed_data_utils'; - -const expect = chai.expect; - -describe('signTypedDataUtils', () => { - describe('signTypedDataHash', () => { - const simpleSignTypedDataHashHex = '0xb460d69ca60383293877cd765c0f97bd832d66bca720f7e32222ce1118832493'; - const simpleSignTypedData = { - types: { - EIP712Domain: [ - { - name: 'name', - type: 'string', - }, - ], - Test: [ - { - name: 'testAddress', - type: 'address', - }, - { - name: 'testNumber', - type: 'uint256', - }, - ], - }, - domain: { - name: 'Test', - }, - message: { - testAddress: '0x0000000000000000000000000000000000000000', - testNumber: '12345', - }, - primaryType: 'Test', - }; - const orderSignTypedDataHashHex = '0x55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692'; - const orderSignTypedData = { - types: { - EIP712Domain: [ - { - name: 'name', - type: 'string', - }, - { - name: 'version', - type: 'string', - }, - { - name: 'verifyingContract', - type: 'address', - }, - ], - Order: [ - { - name: 'makerAddress', - type: 'address', - }, - { - name: 'takerAddress', - type: 'address', - }, - { - name: 'feeRecipientAddress', - type: 'address', - }, - { - name: 'senderAddress', - type: 'address', - }, - { - name: 'makerAssetAmount', - type: 'uint256', - }, - { - name: 'takerAssetAmount', - type: 'uint256', - }, - { - name: 'makerFee', - type: 'uint256', - }, - { - name: 'takerFee', - type: 'uint256', - }, - { - name: 'expirationTimeSeconds', - type: 'uint256', - }, - { - name: 'salt', - type: 'uint256', - }, - { - name: 'makerAssetData', - type: 'bytes', - }, - { - name: 'takerAssetData', - type: 'bytes', - }, - ], - }, - domain: { - name: '0x Protocol', - version: '2', - verifyingContract: '0x0000000000000000000000000000000000000000', - }, - message: { - makerAddress: '0x0000000000000000000000000000000000000000', - takerAddress: '0x0000000000000000000000000000000000000000', - makerAssetAmount: '1000000000000000000', - takerAssetAmount: '1000000000000000000', - expirationTimeSeconds: '12345', - makerFee: '0', - takerFee: '0', - feeRecipientAddress: '0x0000000000000000000000000000000000000000', - senderAddress: '0x0000000000000000000000000000000000000000', - salt: '12345', - makerAssetData: '0x0000000000000000000000000000000000000000', - takerAssetData: '0x0000000000000000000000000000000000000000', - exchangeAddress: '0x0000000000000000000000000000000000000000', - }, - primaryType: 'Order', - }; - it('creates a hash of the test sign typed data', () => { - const hash = signTypedDataUtils.generateTypedDataHash(simpleSignTypedData).toString('hex'); - const hashHex = `0x${hash}`; - expect(hashHex).to.be.eq(simpleSignTypedDataHashHex); - }); - it('creates a hash of the order sign typed data', () => { - const hash = signTypedDataUtils.generateTypedDataHash(orderSignTypedData).toString('hex'); - const hashHex = `0x${hash}`; - expect(hashHex).to.be.eq(orderSignTypedDataHashHex); - }); - it('creates a hash of an uninitialized order', () => { - const uninitializedOrder = { - ...orderSignTypedData, - message: { - makerAddress: '0x0000000000000000000000000000000000000000', - takerAddress: '0x0000000000000000000000000000000000000000', - makerAssetAmount: 0, - takerAssetAmount: 0, - expirationTimeSeconds: 0, - makerFee: 0, - takerFee: 0, - feeRecipientAddress: '0x0000000000000000000000000000000000000000', - senderAddress: '0x0000000000000000000000000000000000000000', - salt: 0, - makerAssetData: '0x0000000000000000000000000000000000000000', - takerAssetData: '0x0000000000000000000000000000000000000000', - exchangeAddress: '0x0000000000000000000000000000000000000000', - }, - }; - const hash = signTypedDataUtils.generateTypedDataHash(uninitializedOrder).toString('hex'); - const hashHex = `0x${hash}`; - expect(hashHex).to.be.eq('0xfaa49b35faeb9197e9c3ba7a52075e6dad19739549f153b77dfcf59408a4b422'); - }); - }); -}); diff --git a/packages/utils/test/utils/chai_setup.ts b/packages/utils/test/utils/chai_setup.ts deleted file mode 100644 index 1a8733093..000000000 --- a/packages/utils/test/utils/chai_setup.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as chai from 'chai'; -import chaiAsPromised = require('chai-as-promised'); -import ChaiBigNumber = require('chai-bignumber'); -import * as dirtyChai from 'dirty-chai'; - -export const chaiSetup = { - configure(): void { - chai.config.includeStack = true; - chai.use(ChaiBigNumber()); - chai.use(dirtyChai); - chai.use(chaiAsPromised); - }, -}; diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json deleted file mode 100644 index 718e623c7..000000000 --- a/packages/utils/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig", - "compilerOptions": { - "outDir": "lib", - "rootDir": "." - }, - "include": ["src/**/*", "test/**/*"] -} diff --git a/packages/utils/tslint.json b/packages/utils/tslint.json deleted file mode 100644 index dd9053357..000000000 --- a/packages/utils/tslint.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["@0x/tslint-config"] -} |