aboutsummaryrefslogtreecommitdiffstats
path: root/packages/utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/utils/src')
-rw-r--r--packages/utils/src/abi_decoder.ts52
-rw-r--r--packages/utils/src/address_utils.ts26
-rw-r--r--packages/utils/src/types.ts4
3 files changed, 29 insertions, 53 deletions
diff --git a/packages/utils/src/abi_decoder.ts b/packages/utils/src/abi_decoder.ts
index e8a222229..b764e45b8 100644
--- a/packages/utils/src/abi_decoder.ts
+++ b/packages/utils/src/abi_decoder.ts
@@ -16,7 +16,7 @@ import * as _ from 'lodash';
import { AbiEncoder } from '.';
import { addressUtils } from './address_utils';
import { BigNumber } from './configured_bignumber';
-import { FunctionInfoBySelector, TransactionData } from './types';
+import { DecodedCalldata, SelectorToFunctionInfo } from './types';
/**
* AbiDecoder allows you to decode event logs given a set of supplied contract ABI's. It takes the contract's event
@@ -24,17 +24,17 @@ import { FunctionInfoBySelector, TransactionData } from './types';
*/
export class AbiDecoder {
private readonly _eventIds: { [signatureHash: string]: { [numIndexedArgs: number]: EventAbi } } = {};
- private readonly _functionInfoBySelector: FunctionInfoBySelector = {};
+ private readonly _selectorToFunctionInfo: SelectorToFunctionInfo = {};
/**
- * Retrieves the function selector from tranasction data.
- * @param calldata hex-encoded transaction data.
+ * Retrieves the function selector from calldata.
+ * @param calldata hex-encoded calldata.
* @return hex-encoded function selector.
*/
private static _getFunctionSelector(calldata: string): string {
const functionSelectorLength = 10;
if (!calldata.startsWith('0x') || calldata.length < functionSelectorLength) {
throw new Error(
- `Malformed transaction data. Must include a hex prefix '0x' and 4-byte function selector. Got '${calldata}'`,
+ `Malformed calldata. Must include a hex prefix '0x' and 4-byte function selector. Got '${calldata}'`,
);
}
const functionSelector = calldata.substr(0, functionSelectorLength);
@@ -56,12 +56,12 @@ export class AbiDecoder {
* @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 eventId = log.topics[0];
const numIndexedArgs = log.topics.length - 1;
- if (_.isUndefined(this._eventIds[methodId]) || _.isUndefined(this._eventIds[methodId][numIndexedArgs])) {
+ if (_.isUndefined(this._eventIds[eventId]) || _.isUndefined(this._eventIds[eventId][numIndexedArgs])) {
return log;
}
- const event = this._eventIds[methodId][numIndexedArgs];
+ const event = this._eventIds[eventId][numIndexedArgs];
const ethersInterface = new ethers.utils.Interface([event]);
const decodedParams: DecodedLogArgs = {};
let topicsIndex = 1;
@@ -110,19 +110,21 @@ export class AbiDecoder {
}
}
/**
- * Decodes transaction data for a known ABI.
- * @param calldata hex-encoded transaction data.
+ * Decodes calldata for a known ABI.
+ * @param calldata hex-encoded calldata.
* @param contractName used to disambiguate similar ABI's (optional).
- * @return Decoded transaction data. Includes: function name and signature, along with the decoded arguments.
+ * @return Decoded calldata. Includes: function name and signature, along with the decoded arguments.
*/
- public tryDecodeCalldata(calldata: string, contractName?: string): TransactionData {
+ public decodeCalldataOrThrow(calldata: string, contractName?: string): DecodedCalldata {
const functionSelector = AbiDecoder._getFunctionSelector(calldata);
- const candidateFunctionInfos = this._functionInfoBySelector[functionSelector];
+ const candidateFunctionInfos = this._selectorToFunctionInfo[functionSelector];
if (_.isUndefined(candidateFunctionInfos)) {
throw new Error(`No functions registered for selector '${functionSelector}'`);
}
- const functionInfo = _.find(candidateFunctionInfos, txDecoder => {
- return _.isUndefined(contractName) || _.toLower(txDecoder.contractName) === _.toLower(contractName);
+ const functionInfo = _.find(candidateFunctionInfos, candidateFunctionInfo => {
+ return (
+ _.isUndefined(contractName) || _.toLower(contractName) === _.toLower(candidateFunctionInfo.contractName)
+ );
});
if (_.isUndefined(functionInfo)) {
throw new Error(
@@ -144,12 +146,14 @@ export class AbiDecoder {
return decodedCalldata;
}
/**
- * Adds a set of ABI definitions, after which transaction data targeting these ABI's can be decoded.
+ * Adds a set of ABI definitions, after which calldata and logs targeting these ABI's can be decoded.
* Additional properties can be included to disambiguate similar ABI's. For example, if two functions
* have the same signature but different parameter names, then their ABI definitions can be disambiguated
* by specifying a contract name.
* @param abiDefinitions ABI definitions for a given contract.
* @param contractName Name of contract that encapsulates the ABI definitions (optional).
+ * This can be used when decoding calldata to disambiguate methods with
+ * the same signature but different parameter names.
*/
public addABI(abiArray: AbiDefinition[], contractName?: string): void {
if (_.isUndefined(abiArray)) {
@@ -159,15 +163,13 @@ export class AbiDecoder {
_.map(abiArray, (abi: AbiDefinition) => {
switch (abi.type) {
case AbiType.Event:
- // tslint:disable no-unnecessary-type-assertion
+ // tslint:disable-next-line:no-unnecessary-type-assertion
this._addEventABI(abi as EventAbi, ethersInterface);
- // tslint:enable no-unnecessary-type-assertion
break;
case AbiType.Function:
- // tslint:disable no-unnecessary-type-assertion
+ // tslint:disable-next-line:no-unnecessary-type-assertion
this._addMethodABI(abi as MethodAbi, contractName);
- // tslint:enable no-unnecessary-type-assertion
break;
default:
@@ -176,9 +178,7 @@ export class AbiDecoder {
}
});
}
- private _addEventABI(abi: EventAbi, ethersInterface: ethers.utils.Interface): void {
- // tslint:disable-next-line:no-unnecessary-type-assertion
- const eventAbi = abi as EventAbi;
+ private _addEventABI(eventAbi: EventAbi, ethersInterface: ethers.utils.Interface): void {
const topic = ethersInterface.events[eventAbi.name].topic;
const numIndexedArgs = _.reduce(eventAbi.inputs, (sum, input) => (input.indexed ? sum + 1 : sum), 0);
this._eventIds[topic] = {
@@ -189,12 +189,12 @@ export class AbiDecoder {
private _addMethodABI(methodAbi: MethodAbi, contractName?: string): void {
const abiEncoder = new AbiEncoder.Method(methodAbi);
const functionSelector = abiEncoder.getSelector();
- if (!(functionSelector in this._functionInfoBySelector)) {
- this._functionInfoBySelector[functionSelector] = [];
+ if (!(functionSelector in this._selectorToFunctionInfo)) {
+ this._selectorToFunctionInfo[functionSelector] = [];
}
// Recored a copy of this ABI for each deployment
const functionSignature = abiEncoder.getSignature();
- this._functionInfoBySelector[functionSelector].push({
+ this._selectorToFunctionInfo[functionSelector].push({
functionSignature,
abiEncoder,
contractName,
diff --git a/packages/utils/src/address_utils.ts b/packages/utils/src/address_utils.ts
index b269c26b4..1fc960408 100644
--- a/packages/utils/src/address_utils.ts
+++ b/packages/utils/src/address_utils.ts
@@ -1,13 +1,10 @@
-import { addHexPrefix, sha3, stripHexPrefix } from 'ethereumjs-util';
+import { addHexPrefix, stripHexPrefix } from 'ethereumjs-util';
import * as jsSHA3 from 'js-sha3';
import * as _ from 'lodash';
-import { BigNumber } from './configured_bignumber';
-
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;
-const MAX_DIGITS_IN_UNSIGNED_256_INT = 78;
export const addressUtils = {
isChecksumAddress(address: string): boolean {
@@ -46,25 +43,4 @@ export const addressUtils = {
padZeros(address: string): string {
return addHexPrefix(_.padStart(stripHexPrefix(address), ADDRESS_LENGTH, '0'));
},
- /**
- * Generates a pseudo-random 256-bit salt.
- * The salt can be included in a 0x order, ensuring that the order generates a unique orderHash
- * and will not collide with other outstanding orders that are identical in all other parameters.
- * @return A pseudo-random 256-bit number that can be used as a salt.
- */
- generatePseudoRandomSalt(): BigNumber {
- // BigNumber.random returns a pseudo-random number between 0 & 1 with a passed in number of decimal places.
- // Source: https://mikemcl.github.io/bignumber.js/#random
- const randomNumber = BigNumber.random(MAX_DIGITS_IN_UNSIGNED_256_INT);
- const factor = new BigNumber(10).pow(MAX_DIGITS_IN_UNSIGNED_256_INT - 1);
- const salt = randomNumber.times(factor);
- return salt;
- },
- generatePseudoRandomAddress(): string {
- const randomBigNum = addressUtils.generatePseudoRandomSalt();
- const randomBuff = sha3(randomBigNum.toString());
- const addressLengthInBytes = 20;
- const randomAddress = `0x${randomBuff.slice(0, addressLengthInBytes).toString('hex')}`;
- return randomAddress;
- },
};
diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts
index cd7a13d53..32e11efa2 100644
--- a/packages/utils/src/types.ts
+++ b/packages/utils/src/types.ts
@@ -8,11 +8,11 @@ export interface FunctionInfo {
abiEncoder?: AbiEncoder.Method;
}
-export interface FunctionInfoBySelector {
+export interface SelectorToFunctionInfo {
[index: string]: FunctionInfo[];
}
-export interface TransactionData {
+export interface DecodedCalldata {
functionName: string;
functionSignature: string;
functionArguments: any;