aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hysen <greg.hysen@gmail.com>2019-01-31 02:52:13 +0800
committerGreg Hysen <greg.hysen@gmail.com>2019-02-09 08:25:30 +0800
commit8fc3a6b828e6f3a5f1aacfc62f585834f012ce7a (patch)
tree10a9054f1c380b7c267703fa1b463cad1440086a
parent100840b74359e00bda90146f87ddeafd62db06e3 (diff)
downloaddexon-0x-contracts-8fc3a6b828e6f3a5f1aacfc62f585834f012ce7a.tar.gz
dexon-0x-contracts-8fc3a6b828e6f3a5f1aacfc62f585834f012ce7a.tar.zst
dexon-0x-contracts-8fc3a6b828e6f3a5f1aacfc62f585834f012ce7a.zip
Expanding search parameters for transaction decoder
-rw-r--r--packages/utils/src/calldata_decoder.ts93
1 files changed, 87 insertions, 6 deletions
diff --git a/packages/utils/src/calldata_decoder.ts b/packages/utils/src/calldata_decoder.ts
index 780332514..0279aa030 100644
--- a/packages/utils/src/calldata_decoder.ts
+++ b/packages/utils/src/calldata_decoder.ts
@@ -5,18 +5,41 @@ import { SimpleContractArtifact } from '@0x/types';
import { ContractAbi, MethodAbi } from 'ethereum-types';
import * as _ from 'lodash';
import { AbiEncoder } from '.';
+import { ContractAddresses, getContractAddressesForNetworkOrThrow, NetworkId } from '@0x/contract-addresses';
export interface DecodedCalldata {
functionName: string;
functionSignature: string;
functionArguments: any;
+ contractName: string;
+ deployedAddress?: string;
+ deployedNeworkId?: string;
+}
+
+interface AbiEncoderBySelectorElement {
+ abiEncoder: AbiEncoder.Method;
+ contractName?: string;
+ contractAddress?: string;
+}
+
+interface AbiEncoderByNeworkId {
+ [index: string]: AbiEncoderBySelectorElement;
}
interface AbiEncoderBySelector {
- [index: string]: AbiEncoder.Method;
+ [index: string]: AbiEncoderByNeworkId;
+}
+
+interface DeployedContractInfoByNetwork {
+ [index: number]: string;
+}
+
+interface DeployedContractInfoByName {
+ [index: string]: DeployedContractInfoByNetwork;
}
export class CalldataDecoder {
+ private readonly _deployedContractInfoByName = {} as DeployedContractInfoByName;
private readonly _abiEncoderBySelector: AbiEncoderBySelector = {};
private static _instance: CalldataDecoder;
@@ -27,7 +50,15 @@ export class CalldataDecoder {
return CalldataDecoder._instance;
}
- public constructor() {
+ private constructor() {
+ // Load addresses by contract name
+ _.each(NetworkId, (networkId: NetworkId) => {
+ const contractAddressesForNetwork = getContractAddressesForNetworkOrThrow(networkId);
+ _.each(contractAddressesForNetwork, (contractAddress: string, contractName: string) => {
+ this._deployedContractInfoByName[contractName][networkId as number] = contractAddress;
+ });
+ });
+ // Load contract artifacts
_.each(ContractArtifacts, (contractArtifactAsJson: any) => {
const conractArtifact = contractArtifactAsJson as SimpleContractArtifact;
const contractAbi: ContractAbi = conractArtifact.compilerOutput.abi;
@@ -38,21 +69,71 @@ export class CalldataDecoder {
if (_.has(this._abiEncoderBySelector, functionSelector)) {
return;
}
- this._abiEncoderBySelector[functionSelector] = abiEncoder;
+ this._abiEncoderBySelector[functionSelector][conractArtifact.contractName] = {abiEncoder};
});
});
}
- public static decode(calldata: string, rules?: AbiEncoder.DecodingRules): DecodedCalldata {
+ public static registerContractAbi(contractArtifact: SimpleContractArtifact, deployedAddress?: string, deployedNeworkId?: number) {
+
+ }
+
+ private static getFunctionSelector(calldata: string): string {
if (!calldata.startsWith('0x') || calldata.length < 10) {
throw new Error(`Malformed calldata. Must include hex prefix '0x' and 4-byte function selector. Got '${calldata}'`);
}
const functionSelector = calldata.substr(0, 10);
+ return functionSelector;
+ }
+
+ public static decodeWithContractAddress(calldata: string, contractAddress: string, networkId?: number): DecodedCalldata {
+ const functionSelector = CalldataDecoder.getFunctionSelector(calldata);
const instance = CalldataDecoder.getInstance();
- const abiEncoder = instance._abiEncoderBySelector[functionSelector];
+ const contractName = _.findKey(instance._deployedContractInfoByName, (info: DeployedContractInfoByNetwork) => {
+ return (!_.isUndefined(networkId) && info[networkId] === contractAddress) || (_.isUndefined(networkId) && contractAddress in info);
+ });
+ if (_.isUndefined(contractName)) {
+ throw new Error(`Could not find contract name: ${contractName}`);
+ }
+ const abiEncoder = instance._abiEncoderBySelector[functionSelector][contractName];
if (_.isUndefined(abiEncoder)) {
throw new Error(`Could not find matching abi encoder for selector '${functionSelector}'`);
}
+
+ }
+
+ public static decodeWithContractName(calldata: string, contractName: string): DecodedCalldata {
+ const functionSelector = CalldataDecoder.getFunctionSelector(calldata);
+ const instance = CalldataDecoder.getInstance();
+ const abiEncoder = instance._abiEncoderBySelector[functionSelector][contractName];
+ if (_.isUndefined(abiEncoder)) {
+ throw new Error(`Could not find matching abi encoder for selector '${functionSelector}'`);
+ }
+ }
+
+ public static decodeWithoutContractInfo(calldata: string): DecodedCalldata {
+ const functionSelector = CalldataDecoder.getFunctionSelector(calldata);
+ const instance = CalldataDecoder.getInstance();
+ const abiEncoder = _.find(instance._abiEncoderBySelector[functionSelector], () => {return true});
+ if (_.isUndefined(abiEncoder)) {
+ throw new Error(`Could not find matching abi encoder for selector '${functionSelector}'`);
+ }
+ return {
+ functionName: string;
+ functionSignature: string;
+ functionArguments: any;
+ contractName: string;
+ deployedAddress?: string;
+ deployedNeworkId?: string;
+ };
+ }
+
+ public static decode(calldata: string, contractName?: string, contractAddress?: string, networkId?: number, rules?: AbiEncoder.DecodingRules): DecodedCalldata {
+
+
+
+
+ /*
const functionName = abiEncoder.getDataItem().name;
const functionSignature = abiEncoder.getSignatureType();
const functionArguments = abiEncoder.decode(calldata, rules);
@@ -61,6 +142,6 @@ export class CalldataDecoder {
functionSignature,
functionArguments
}
- return decodedCalldata;
+ return decodedCalldata;*/
}
} \ No newline at end of file