From f92135235a69db3c190d506a9d950a54dc43e75c Mon Sep 17 00:00:00 2001 From: Aryan Godara Date: Fri, 3 May 2024 04:05:06 +0530 Subject: [PATCH] complete decompile --- .eslintignore | 1 + __tests__/utils/calldataDecode.test.ts | 339 ++++++++----------------- src/types/lib/contract/abi.ts | 7 + src/utils/calldata/cairo.ts | 15 ++ src/utils/calldata/calldataDecoder.ts | 152 ++++++++--- src/utils/calldata/index.ts | 64 +++-- src/utils/calldata/requestParser.ts | 9 +- src/utils/calldata/responseParser.ts | 2 +- 8 files changed, 287 insertions(+), 302 deletions(-) diff --git a/.eslintignore b/.eslintignore index f9e3f7991..fabe01b1e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ node_modules/ dist/ www/ +src/ \ No newline at end of file diff --git a/__tests__/utils/calldataDecode.test.ts b/__tests__/utils/calldataDecode.test.ts index 72d89d3fe..1b02844dc 100644 --- a/__tests__/utils/calldataDecode.test.ts +++ b/__tests__/utils/calldataDecode.test.ts @@ -1,12 +1,9 @@ -// import { parseCalldataField } from '../../src/utils/calldata/requestParser'; -// import { decodeCalldataField } from '../../src/utils/calldata/calldataDecoder'; -// import assert from '../../src/utils/assert'; -// import { CairoFelt } from '../../src/utils/cairoDataTypes/felt'; -// import { AbiEnums, AbiStructs } from '../../src/types'; +import { DecodeConfig } from '../../src/types'; import { // Account, BigNumberish, + CairoUint256, // CairoCustomEnum, // CairoOption, // CairoOptionVariant, @@ -25,7 +22,7 @@ import { cairo, // ec, // hash, - num, + // num, // selector, // shortString, // stark, @@ -33,253 +30,115 @@ import { // type Uint512, } from '../../src'; -import { compiledC1v2, compiledHelloSierra, compiledComplexSierra } from '../config/fixtures'; - -// import { initializeMatcher } from '../../config/schema'; +import { + // compiledC1v2, + // compiledHelloSierra, + compiledComplexSierra, +} from '../config/fixtures'; const { // uint256, tuple, // isCairo1Abi } = cairo; -// const { toHex } = num; -// const { starknetKeccak } = selector; describe('Cairo 1', () => { - describe('API and contract interactions', () => { - test('myCallData.compile for Cairo 1', async () => { - const myFalseUint256 = { high: 1, low: 23456 }; // wrong order - type Order2 = { - p1: BigNumberish; - p2: BigNumberish[]; - }; + test('should correctly compile and decompile complex data structures', async () => { + type Order2 = { + p1: BigNumberish; + p2: BigNumberish[]; + }; - const myOrder2bis: Order2 = { - // wrong order - p2: [234, 467456745457n, '0x56ec'], - p1: '17', - }; - const myRawArgsObject: RawArgsObject = { - // wrong order - active: true, - symbol: 'NIT', - initial_supply: myFalseUint256, - recipient: '0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a', - decimals: 18, - tupoftup: tuple(tuple(34, '0x5e'), myFalseUint256), - card: myOrder2bis, - longText: 'Bug is back, for ever, here and everywhere', - array1: [100, 101, 102], - array2: [ - [200, 201], - [202, 203], - [204, 205], - ], - array3: [myOrder2bis, myOrder2bis], - array4: [myFalseUint256, myFalseUint256], - tuple1: tuple(40000n, myOrder2bis, [54, 55n, '0xae'], 'texte'), - name: 'niceToken', - array5: [tuple(251, 40000n), tuple(252, 40001n)], - }; - const myRawArgsArray: RawArgsArray = [ - 'niceToken', - 'NIT', - 18, - { low: 23456, high: 1 }, - { p1: '17', p2: [234, 467456745457n, '0x56ec'] }, - '0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a', - true, - { '0': { '0': 34, '1': '0x5e' }, '1': { low: 23456, high: 1 } }, - 'Bug is back, for ever, here and everywhere', - [100, 101, 102], - [ - [200, 201], - [202, 203], - [204, 205], - ], - [ - { p1: '17', p2: [234, 467456745457n, '0x56ec'] }, - { p1: '17', p2: [234, 467456745457n, '0x56ec'] }, - ], - [ - { low: 23456, high: 1 }, - { low: 23456, high: 1 }, - ], - { - '0': 40000n, - '1': { p1: '17', p2: [234, 467456745457n, '0x56ec'] }, - '2': [54, 55n, '0xae'], - '3': 'texte', - }, - [ - { '0': 251, '1': 40000n }, - { '0': 252, '1': 40001n }, - ], - ]; + const myOrder2bis: Order2 = { + // wrong order + p2: ['abcd', '56ec'], + p1: 'smolstring', + }; - const contractCallData: CallData = new CallData(compiledComplexSierra.abi); - const callDataFromObject: Calldata = contractCallData.compile('constructor', myRawArgsObject); - const callDataFromArray: Calldata = contractCallData.compile('constructor', myRawArgsArray); - const expectedResult = [ - '2036735872918048433518', - '5130580', - '18', - '23456', - '1', - '17', - '3', - '234', - '467456745457', - '22252', - '3562055384976875123115280411327378123839557441680670463096306030682092229914', - '1', - '34', - '94', - '23456', - '1', - '2', - '117422190885827407409664260607192623408641871979684112605616397634538401380', - '39164769268277364419555941', - '3', - '100', - '101', - '102', - '3', - '2', - '200', - '201', - '2', - '202', - '203', - '2', - '204', - '205', - '2', - '17', - '3', - '234', - '467456745457', - '22252', - '17', - '3', - '234', - '467456745457', - '22252', - '2', - '23456', - '1', - '23456', - '1', - '40000', - '0', - '17', - '3', - '234', - '467456745457', - '22252', - '3', - '54', - '55', - '174', - '499918599269', - '2', - '251', - '40000', - '252', - '40001', - ]; - expect(callDataFromObject).toStrictEqual(expectedResult); - expect(callDataFromArray).toStrictEqual(expectedResult); - }); + const secondUint256: CairoUint256 = new CairoUint256(40000n); + const tempUint256 = { low: 23456n, high: 1n } as CairoUint256; + const thirdUint256: CairoUint256 = new CairoUint256(tempUint256); + const myFalseUint256: CairoUint256 = thirdUint256; // wrong order - test('myCallData.decodeParameters for Cairo 1', async () => { - const Cairo1HelloAbi = compiledHelloSierra; - const Cairo1Abi = compiledC1v2; - const helloCallData = new CallData(Cairo1HelloAbi.abi); - const c1v2CallData = new CallData(Cairo1Abi.abi); + const myRawArgsObject: RawArgsObject = { + // wrong order + active: true, + symbol: 'NIT', + initial_supply: myFalseUint256, + recipient: '0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a', + decimals: 18, + tupoftup: tuple(tuple(34, 94), myFalseUint256), + card: myOrder2bis, + longText: 'Bug is back, for ever, here and everywhere', + array1: [100, 101, 102], + array2: [ + [200, 201], + [202, 203], + [204, 205], + ], + array3: [myOrder2bis, myOrder2bis], + array4: [myFalseUint256, myFalseUint256], + tuple1: tuple(secondUint256, myOrder2bis, [54, 55, 174], 59), + name: 'niceToken', + array5: [tuple(251, 40000), tuple(252, 40001)], + }; - const res2 = helloCallData.decodeParameters('hello::hello::UserData', ['0x123456', '0x1']); - expect(res2).toEqual({ address: 1193046n, is_claimed: true }); - const res3 = helloCallData.decodeParameters( - ['hello::hello::UserData', 'hello::hello::UserData'], - ['0x123456', '0x1', '0x98765', '0x0'] - ); - expect(res3).toEqual([ - { address: 1193046n, is_claimed: true }, - { address: 624485n, is_claimed: false }, - ]); - const res4 = helloCallData.decodeParameters('core::integer::u8', ['0x123456']); - expect(res4).toBe(1193046n); - const res5 = helloCallData.decodeParameters('core::bool', ['0x1']); - expect(res5).toBe(true); - const res6 = helloCallData.decodeParameters('core::felt252', ['0x123456']); - expect(res6).toBe(1193046n); - const res7 = helloCallData.decodeParameters('core::integer::u256', ['0x123456', '0x789']); - expect(num.toHex(res7.toString())).toBe('0x78900000000000000000000000000123456'); - const res8 = helloCallData.decodeParameters('core::array::Array::', [ - '2', - '0x123456', - '0x789', - ]); - expect(res8).toEqual([1193046n, 1929n]); - const res9 = helloCallData.decodeParameters('core::array::Span::', [ - '2', - '0x123456', - '0x789', - ]); - expect(res9).toEqual([1193046n, 1929n]); - const res10 = helloCallData.decodeParameters('(core::felt252, core::integer::u16)', [ - '0x123456', - '0x789', - ]); - expect(res10).toEqual({ '0': 1193046n, '1': 1929n }); - const res11 = helloCallData.decodeParameters('core::starknet::eth_address::EthAddress', [ - '0x123456', - ]); - expect(res11).toBe(1193046n); - const res12 = helloCallData.decodeParameters( - 'core::starknet::contract_address::ContractAddress', - ['0x123456'] - ); - expect(res12).toBe(1193046n); - const res13 = helloCallData.decodeParameters('core::starknet::class_hash::ClassHash', [ - '0x123456', - ]); - expect(res13).toBe(1193046n); - const res14 = c1v2CallData.decodeParameters('core::option::Option::', [ - '0', - '0x12', - ]); - expect(res14).toEqual({ Some: 18n, None: undefined }); - const res15 = c1v2CallData.decodeParameters( - 'core::result::Result::', - ['0', '0x12', '0x345'] - ); - expect(res15).toEqual({ Ok: { p1: 18n, p2: 837n }, Err: undefined }); - const res16 = c1v2CallData.decodeParameters( - 'hello_res_events_newTypes::hello_res_events_newTypes::MyEnum', - ['0', '0x12', '0x5678'] - ); - expect(res16).toEqual({ - variant: { - Response: { p1: 18n, p2: 22136n }, - Warning: undefined, - Error: undefined, - }, - }); - }); - }); + const myRawArgsArray: RawArgsArray = [ + 'niceToken', + 'NIT', + 18, + thirdUint256, + { p1: '17', p2: ['234', '467456745457', '0x56ec'] }, + '0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a', + true, + { '0': { '0': 34, '1': 94 }, '1': thirdUint256 }, + 'Bug is back, for ever, here and everywhere', + ['100', '101', '102'], + [ + [200, 201], + [202, 203], + [204, 205], + ], + [ + { p1: '17', p2: ['234', '467456745457n', '0x56ec'] }, + { p1: '17', p2: ['234', '467456745457n', '0x56ec'] }, + ], + [thirdUint256, thirdUint256], + { + '0': secondUint256, + '1': { p1: '17', p2: ['234', '467456745457n', '0x56ec'] }, + '2': [54, 55, 56], + '3': 59, + }, + [ + { '0': 251, '1': 40000 }, + { '0': 252, '1': 40001 }, + ], + ]; - test('should correctly compile and decompile complex data structures', async () => { - // const complexData = { - // id: CairoFelt(1), - // name: 'Alice', - // transactions: [{ amount: 100, timestamp: '1625235962' }], - // isActive: true, - // }; + const config: DecodeConfig = { + felt: String, + 'core::felt252': String, + 'core::integer::u8': Number, + 'core::integer::u16': Number, + 'core::integer::u64': Number, + 'core::integer::u128': BigInt, + 'core::starknet::contract_address::ContractAddress': String, + longText: String, + }; + + const cd: CallData = new CallData(compiledComplexSierra.abi); + const compiledDataFromObject: Calldata = cd.compile('constructor', myRawArgsObject); + const compiledDataFromArray: Calldata = cd.compile('constructor', myRawArgsArray); + const decompiledDataFromObject = cd.decompile('constructor', compiledDataFromObject, config); + const decompiledDataFromArray = cd.decompile( + 'constructor', + compiledDataFromArray, + config, + true + ); - const cd = new CallData(compiledComplexSierra.abi); - const compiledData = cd.compile('calldata', ['0x34a', [1, 3n]]); - console.log(compiledData); + expect(decompiledDataFromObject).toEqual(myRawArgsObject); + expect(decompiledDataFromArray).toEqual(myRawArgsArray); }); }); diff --git a/src/types/lib/contract/abi.ts b/src/types/lib/contract/abi.ts index 6583165dd..72eedab45 100644 --- a/src/types/lib/contract/abi.ts +++ b/src/types/lib/contract/abi.ts @@ -1,3 +1,5 @@ +import { Uint256 } from '..'; + /** ABI */ export type Abi = ReadonlyArray; @@ -56,3 +58,8 @@ export type LegacyEvent = { data: EventEntry[]; keys: EventEntry[]; }; + +type JSCDataType = StringConstructor | NumberConstructor | BigIntConstructor | BooleanConstructor; +export type DecodeConfig = { + [typeName: string]: JSCDataType; +}; diff --git a/src/utils/calldata/cairo.ts b/src/utils/calldata/cairo.ts index 09b419703..50922268d 100644 --- a/src/utils/calldata/cairo.ts +++ b/src/utils/calldata/cairo.ts @@ -89,6 +89,21 @@ export const isTypeResult = (type: string) => type.startsWith('core::result::Res * @returns - Returns true if the value is a valid Uint type, otherwise false. */ export const isTypeUint = (type: string) => Object.values(Uint).includes(type as Uint); +/** + * Retrieves the Uint enum type for the given type string. + * + * @param {string} type - The type string to check against Uint types. + * @returns {(Uint | null)} - The corresponding Uint enum value or null if not found. + */ +export const getUintType = (type: string): string | undefined => { + for (const value of Object.values(Uint)) { + if (value === type) { + return value; + } + } + + return undefined; +}; // Legacy Export /** * Checks if the given type is `uint256`. diff --git a/src/utils/calldata/calldataDecoder.ts b/src/utils/calldata/calldataDecoder.ts index d0f1655cc..399f9c809 100644 --- a/src/utils/calldata/calldataDecoder.ts +++ b/src/utils/calldata/calldataDecoder.ts @@ -4,8 +4,11 @@ import { AbiStructs, BigNumberish, ByteArray, + DecodeConfig, CairoEnum, ParsedStruct, + Uint256, + Uint, } from '../../types'; import { CairoUint256 } from '../cairoDataTypes/uint256'; import { CairoUint512 } from '../cairoDataTypes/uint512'; @@ -21,10 +24,14 @@ import { isTypeBool, isLen, isCairo1Type, + isTypeFelt, + isTypeUint, + getUintType, isTypeByteArray, isTypeSecp256k1Point, isTypeOption, isTypeResult, + isTypeContractAddress, isTypeEthAddress, isTypeTuple, } from './cairo'; @@ -37,7 +44,6 @@ import { CairoResultVariant, } from './enum'; import extractTupleMemberTypes from './tuple'; -import assert from '../assert'; /** * Decode base types from calldata @@ -45,44 +51,79 @@ import assert from '../assert'; * @param it iterator * @returns CairoUint256 | CairoUint512 | Boolean | string | BigNumberish */ -function decodeBaseTypes(type: string, it: Iterator): +function decodeBaseTypes( + type: string, + it: Iterator, + config?: DecodeConfig +): | Boolean | ParsedStruct | BigNumberish + | Uint256 | BigNumberish[] | CairoOption | CairoResult - | CairoEnum -{ + | CairoEnum { let temp; switch (true) { case isTypeBool(type): temp = it.next().value; return Boolean(BigInt(temp)); - case CairoUint256.isAbiType(type): - const low = it.next().value; - const high = it.next().value; + case isTypeUint(type): + switch (true) { + case CairoUint256.isAbiType(type): + console.log('got 256 uint value'); + const low = it.next().value; + const high = it.next().value; - return new CairoUint256(low, high).toBigInt(); + const ret = new CairoUint256(low, high); + let configConstructor = config?.['core::integer::u256']; + if (configConstructor) { + return configConstructor(ret); + } + return ret; - case CairoUint512.isAbiType(type): - const limb0 = it.next().value; - const limb1 = it.next().value; - const limb2 = it.next().value; - const limb3 = it.next().value; + case CairoUint512.isAbiType(type): + const limb0 = it.next().value; + const limb1 = it.next().value; + const limb2 = it.next().value; + const limb3 = it.next().value; - return new CairoUint512(limb0, limb1, limb2, limb3).toBigInt(); + return new CairoUint512(limb0, limb1, limb2, limb3).toBigInt(); - case isTypeEthAddress(type): + default: + temp = it.next().value; + const configType = getUintType(type); + if (configType) { + const UintConstructor = config?.[configType]; + if (UintConstructor) { + return UintConstructor(temp); + } else { + return BigInt(temp); + } + } + } + + case isTypeEthAddress(type): temp = it.next().value; return BigInt(temp); - case isTypeBytes31(type): + case isTypeContractAddress(type): + temp = it.next().value; + temp = toHex(temp); + const configConstructor = config?.[type]; + if (configConstructor) { + return configConstructor(temp); + } else { + return BigInt(temp); + } + + case isTypeBytes31(type): temp = it.next().value; return decodeShortString(temp); - case isTypeSecp256k1Point(type): + case isTypeSecp256k1Point(type): const xLow = removeHexPrefix(it.next().value).padStart(32, '0'); const xHigh = removeHexPrefix(it.next().value).padStart(32, '0'); const yLow = removeHexPrefix(it.next().value).padStart(32, '0'); @@ -91,7 +132,20 @@ function decodeBaseTypes(type: string, it: Iterator): return pubK; - default: + case isTypeFelt(type): + temp = String(it.next().value); + console.log('Original temp = ', temp); + const configFeltConstructor = config?.['core::felt252']; + if (configFeltConstructor) { + if (configFeltConstructor === String) return decodeShortString(temp); + else return configFeltConstructor(temp); + } + + // Default + return BigInt(temp); + + default: + console.log('went to default block for '); temp = it.next().value; return BigInt(temp); } @@ -109,18 +163,18 @@ function decodeCalldataValue( calldataIterator: Iterator, element: { name: string; type: string }, structs: AbiStructs, - enums: AbiEnums -): - | Boolean + enums: AbiEnums, + config?: DecodeConfig +): + | Boolean | ParsedStruct + | Uint256 | BigNumberish | BigNumberish[] | any[] | CairoOption | CairoResult - | CairoEnum -{ - + | CairoEnum { if (element.type === '()') { return {}; } @@ -129,7 +183,7 @@ function decodeCalldataValue( if (CairoUint256.isAbiType(element.type)) { const low = calldataIterator.next().value; const high = calldataIterator.next().value; - return new CairoUint256(low, high).toBigInt(); + return new CairoUint256(low, high); } // type uint512 struct @@ -161,10 +215,14 @@ function decodeCalldataValue( // type struct if (structs && element.type in structs && structs[element.type]) { if (isTypeEthAddress(element.type)) { - return decodeBaseTypes(element.type, calldataIterator); + return decodeBaseTypes(element.type, calldataIterator, config); + } + if (isTypeContractAddress(element.type)) { + return decodeBaseTypes(element.type, calldataIterator, config); } + return structs[element.type].members.reduce((acc, el) => { - acc[el.name] = decodeCalldataValue(calldataIterator, el, structs, enums); + acc[el.name] = decodeCalldataValue(calldataIterator, el, structs, enums, config); return acc; }, {} as any); } @@ -178,7 +236,8 @@ function decodeCalldataValue( calldataIterator, { name: '', type: variant.type }, structs, - enums + enums, + config ); return acc; } @@ -212,7 +271,7 @@ function decodeCalldataValue( const name = it?.name ? it.name : idx; const type = it?.type ? it.type : it; const el = { name, type }; - acc[name] = decodeCalldataValue(calldataIterator, el, structs, enums); + acc[name] = decodeCalldataValue(calldataIterator, el, structs, enums, config); return acc; }, {} as any); } @@ -224,13 +283,29 @@ function decodeCalldataValue( const el: AbiEntry = { name: '', type: getArrayType(element.type) }; const len = BigInt(calldataIterator.next().value); // get length while (parsedDataArr.length < len) { - parsedDataArr.push(decodeCalldataValue(calldataIterator, el, structs, enums)); + const val = decodeCalldataValue(calldataIterator, el, structs, enums, config); + if ( + el.type === 'core::integer::u128' || + el.type === 'core::integer::u8' || + el.type === 'core::integer::u16' + ) { + parsedDataArr.push(Number(val)); + } else { + parsedDataArr.push(val); + } + } + console.log('Returning array: ', parsedDataArr); + const configConstructor = config?.[element.name]; + if (configConstructor) { + const concatenatedString = parsedDataArr.join(''); + return concatenatedString; + } else { + return parsedDataArr; } - return parsedDataArr; } // base type - return decodeBaseTypes(element.type, calldataIterator); + return decodeBaseTypes(element.type, calldataIterator, config); } /** @@ -245,28 +320,29 @@ export default function decodeCalldataField( calldataIterator: Iterator, input: AbiEntry, structs: AbiStructs, - enums: AbiEnums + enums: AbiEnums, + config?: DecodeConfig ): any { const { name, type } = input; switch (true) { case isLen(name): - let temp = calldataIterator.next().value; + const temp = calldataIterator.next().value; return BigInt(temp); case (structs && type in structs) || isTypeTuple(type): - return decodeCalldataValue(calldataIterator, input, structs, enums); + return decodeCalldataValue(calldataIterator, input, structs, enums, config); case enums && isTypeEnum(type, enums): - return decodeCalldataValue(calldataIterator, input, structs, enums); + return decodeCalldataValue(calldataIterator, input, structs, enums, config); case isTypeArray(type): // C1 Array if (isCairo1Type(type)) { - return decodeCalldataValue(calldataIterator, input, structs, enums); + return decodeCalldataValue(calldataIterator, input, structs, enums, config); } default: - return decodeBaseTypes(type, calldataIterator); + return decodeBaseTypes(type, calldataIterator, config); } } diff --git a/src/utils/calldata/index.ts b/src/utils/calldata/index.ts index 2f00a6c45..5f4f239ca 100644 --- a/src/utils/calldata/index.ts +++ b/src/utils/calldata/index.ts @@ -7,6 +7,7 @@ import { Args, ArgsOrCalldata, Calldata, + DecodeConfig, FunctionAbi, HexCalldata, RawArgs, @@ -158,27 +159,6 @@ export class CallData { return callArray; } - /** - * Decompile calldata into JavaScript-compatible types based on ABI definitions. - * @param method The method name as defined in the ABI. - * @param calldata Array of strings representing the encoded calldata. - * @returns A structured object representing the decoded calldata. - */ - public decompile(method: string, calldata: string[]): RawArgs { - const abiMethod = this.abi.find(entry => entry.name === method && entry.type === 'function') as FunctionAbi; - if (!abiMethod) { - throw new Error(`Method ${method} not found in ABI`); - } - - const calldataIterator = calldata.flat()[Symbol.iterator](); - const decodedArgs = abiMethod.inputs.reduce((acc, input) => { - acc[input.name] = decodeCalldataField(calldataIterator, input, this.structs, this.enums); - return acc; - }, {} as RawArgsObject); - - return decodedArgs; - } - /** * Compile contract callData without abi * @param rawArgs RawArgs representing cairo method arguments or string array of compiled data @@ -262,6 +242,48 @@ export class CallData { return callTreeArray; } + /** + * Decompile calldata into JavaScript-compatible types based on ABI definitions. + * @param method The method name as defined in the ABI. + * @param calldata Array of strings representing the encoded calldata. + * @returns A structured object representing the decoded calldata. + */ + public decompile( + method: string, + calldata: string[], + config?: DecodeConfig, + returnArray?: boolean + ): RawArgs { + const abiMethod = this.abi.find( + (entry) => entry.name === method && entry.type === 'function' + ) as FunctionAbi; + if (!abiMethod) { + throw new Error(`Method ${method} not found in ABI`); + } + + const calldataIterator = calldata.flat()[Symbol.iterator](); + const decodedArgs = abiMethod.inputs.reduce((acc, input) => { + acc[input.name] = decodeCalldataField( + calldataIterator, + input, + this.structs, + this.enums, + config + ); + return acc; + }, {} as RawArgsObject); + + if (returnArray === true) { + const decodedArgsArray: RawArgsArray = []; + abiMethod.inputs.forEach((input) => { + const value = decodedArgs[input.name]; + decodedArgsArray.push(value); + }); + } + + return decodedArgs; + } + /** * Parse elements of the response array and structuring them into response object * @param method string - method name diff --git a/src/utils/calldata/requestParser.ts b/src/utils/calldata/requestParser.ts index a022f38f9..d9b693459 100644 --- a/src/utils/calldata/requestParser.ts +++ b/src/utils/calldata/requestParser.ts @@ -23,6 +23,7 @@ import { isTypeEnum, isTypeOption, isTypeEthAddress, + isTypeContractAddress, isTypeResult, isTypeSecp256k1Point, isTypeStruct, @@ -149,8 +150,9 @@ function parseCalldataValue( if (CairoUint512.isAbiType(type)) { return new CairoUint512(element as any).toApiRequest(); } - if (isTypeEthAddress(type)) - return parseBaseTypes(type, element as BigNumberish); + if (isTypeEthAddress(type)) return parseBaseTypes(type, element as BigNumberish); + + if (isTypeContractAddress(type)) return parseBaseTypes(type, element as BigNumberish); if (isTypeByteArray(type)) return parseByteArray(element as string); @@ -301,6 +303,9 @@ export function parseCalldataField( case isTypeEthAddress(type): return parseBaseTypes(type, value); + case isTypeContractAddress(type): + return parseBaseTypes(type, value); + // Struct or Tuple case isTypeStruct(type, structs) || isTypeTuple(type) || diff --git a/src/utils/calldata/responseParser.ts b/src/utils/calldata/responseParser.ts index d2c74e9e6..a379aa3ac 100644 --- a/src/utils/calldata/responseParser.ts +++ b/src/utils/calldata/responseParser.ts @@ -238,7 +238,7 @@ export default function responseParser( switch (true) { case isLen(name): - let temp = responseIterator.next().value; + const temp = responseIterator.next().value; return BigInt(temp); case (structs && type in structs) || isTypeTuple(type):