Skip to content

Commit fd47b35

Browse files
committed
Better way to decode AA txs
1 parent 0294025 commit fd47b35

File tree

6 files changed

+208
-10
lines changed

6 files changed

+208
-10
lines changed

apps/web/src/app/data.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ export const supportedChains: {
147147
rpcUrl: process.env.BASE_RPC_URL as string,
148148
traceAPI: 'geth',
149149
},
150+
{
151+
name: 'Gnosis mainnet',
152+
chainID: 100,
153+
rpcUrl: process.env.GNOSIS_RPC_URL as string,
154+
// traceAPI: 'geth',
155+
},
150156
{
151157
name: 'Polygon Mainnet',
152158
chainID: 137,
@@ -165,12 +171,6 @@ export const supportedChains: {
165171
rpcUrl: process.env.ARBITRUM_RPC_URL as string,
166172
traceAPI: 'geth',
167173
},
168-
{
169-
name: 'Manta pacific',
170-
chainID: 169,
171-
rpcUrl: (process.env.MANTA_RPC_URL as string) ?? 'https://pacific-rpc.manta.network/http',
172-
traceAPI: 'geth',
173-
},
174174
]
175175

176176
export const defaultTrasaction = EXAMPLE_TXS['AAVE V2'][0]

apps/web/src/lib/decode.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
decodeTransactionByHash,
88
EtherscanV2StrategyResolver,
99
ExperimentalErc20AbiStrategyResolver,
10+
AccountAbstractionStrategyResolver,
1011
FourByteStrategyResolver,
1112
OpenchainStrategyResolver,
1213
SourcifyStrategyResolver,
@@ -29,6 +30,7 @@ const AbiStoreLive = Layer.unwrapEffect(
2930
apikey: apikey,
3031
}),
3132
ExperimentalErc20AbiStrategyResolver(service),
33+
AccountAbstractionStrategyResolver(),
3234
OpenchainStrategyResolver(),
3335
SourcifyStrategyResolver(),
3436
FourByteStrategyResolver(),
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import * as RequestModel from './request-model.js'
2+
import { Effect } from 'effect'
3+
import { Abi } from 'viem'
4+
const AA_ABIS: Record<string, Abi> = {
5+
'0xabc5345e': [
6+
{
7+
name: 'executeBySender',
8+
type: 'function',
9+
stateMutability: 'nonpayable',
10+
inputs: [
11+
{
12+
name: 'calls',
13+
type: 'tuple[]',
14+
components: [
15+
{ name: 'target', type: 'address' },
16+
{ name: 'value', type: 'uint256' },
17+
{ name: 'data', type: 'bytes' },
18+
],
19+
},
20+
],
21+
outputs: [],
22+
},
23+
],
24+
'0x34fcd5be': [
25+
{
26+
inputs: [
27+
{
28+
components: [
29+
{ name: 'target', type: 'address' },
30+
{ name: 'value', type: 'uint256' },
31+
{ name: 'data', type: 'bytes' },
32+
],
33+
name: 'calls',
34+
type: 'tuple[]',
35+
},
36+
],
37+
name: 'executeBatch',
38+
outputs: [],
39+
stateMutability: 'payable',
40+
type: 'function',
41+
},
42+
],
43+
'0x9e5d4c49': [
44+
{
45+
type: 'function',
46+
inputs: [
47+
{ name: 'to', internalType: 'address', type: 'address' },
48+
{ name: 'value', internalType: 'uint256', type: 'uint256' },
49+
{ name: 'data', internalType: 'bytes', type: 'bytes' },
50+
],
51+
name: 'executeCall',
52+
outputs: [
53+
{ name: 'success', internalType: 'bool', type: 'bool' },
54+
{ name: 'returnData', internalType: 'bytes', type: 'bytes' },
55+
],
56+
stateMutability: 'nonpayable',
57+
},
58+
],
59+
'0x912ccaa3': [
60+
{
61+
inputs: [
62+
{
63+
name: 'target',
64+
type: 'address[]',
65+
},
66+
{
67+
name: 'value',
68+
type: 'uint256[]',
69+
},
70+
{
71+
name: 'targetCallData',
72+
type: 'bytes[]',
73+
},
74+
],
75+
name: 'executeBatchCall',
76+
outputs: [],
77+
stateMutability: 'nonpayable',
78+
type: 'function',
79+
},
80+
],
81+
'0x18dfb3c7': [
82+
{
83+
name: 'execute',
84+
type: 'function',
85+
inputs: [
86+
{
87+
name: 'target',
88+
type: 'address[]',
89+
},
90+
{
91+
name: 'callData',
92+
type: 'bytes[]',
93+
},
94+
],
95+
outputs: [],
96+
stateMutability: 'nonpayable',
97+
},
98+
],
99+
'0xb61d27f6': [
100+
{
101+
name: 'execute',
102+
type: 'function',
103+
inputs: [
104+
{
105+
name: 'target',
106+
type: 'address',
107+
},
108+
{
109+
name: 'value',
110+
type: 'uint256',
111+
},
112+
{
113+
name: 'data',
114+
type: 'bytes',
115+
},
116+
],
117+
outputs: [],
118+
stateMutability: 'nonpayable',
119+
},
120+
],
121+
'0x51945447': [
122+
{
123+
type: 'function',
124+
inputs: [
125+
{ name: 'to', internalType: 'address', type: 'address' },
126+
{ name: 'value', internalType: 'uint256', type: 'uint256' },
127+
{ name: 'data', internalType: 'bytes', type: 'bytes' },
128+
{ name: 'operation', internalType: 'enum Operation', type: 'uint8' },
129+
],
130+
name: 'execute',
131+
outputs: [],
132+
stateMutability: 'payable',
133+
},
134+
],
135+
'0xf34308ef': [
136+
{
137+
name: 'execTransactionFromEntrypoint',
138+
type: 'function',
139+
stateMutability: 'payable',
140+
inputs: [
141+
{ name: 'to', type: 'address' },
142+
{ name: 'value', type: 'uint256' },
143+
{ name: 'data', type: 'bytes' },
144+
],
145+
outputs: [],
146+
},
147+
],
148+
'0x541d63c8': [
149+
{
150+
name: 'executeUserOpWithErrorString',
151+
type: 'function',
152+
stateMutability: 'nonpayable',
153+
inputs: [
154+
{ name: 'to', type: 'address' },
155+
{ name: 'value', type: 'uint256' },
156+
{ name: 'data', type: 'bytes' },
157+
{ name: 'operation', type: 'uint8' },
158+
],
159+
outputs: [],
160+
},
161+
],
162+
}
163+
164+
const getLocalFragments = ({ address, chainId, signature }: RequestModel.GetContractABIStrategyParams) =>
165+
Effect.gen(function* () {
166+
if (signature == null) {
167+
return yield* Effect.fail(new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId))
168+
}
169+
170+
const abi = AA_ABIS[signature]
171+
172+
if (abi == null) {
173+
return yield* Effect.fail(new RequestModel.ResolveStrategyABIError('local-strategy', address, chainId))
174+
}
175+
176+
return [
177+
{
178+
type: 'address',
179+
address,
180+
chainID: chainId,
181+
abi: JSON.stringify(abi),
182+
},
183+
] as RequestModel.ContractABI[]
184+
})
185+
186+
export const AccountAbstractionStrategyResolver = (): RequestModel.ContractAbiResolverStrategy => {
187+
return {
188+
id: 'account-abstraction-strategy',
189+
type: 'address',
190+
resolver: (req: RequestModel.GetContractABIStrategyParams) =>
191+
Effect.withSpan(getLocalFragments(req), 'AbiStrategy.AccountAbstractionStrategyResolver', {
192+
attributes: { chainId: req.chainId, address: req.address },
193+
}),
194+
}
195+
}

packages/transaction-decoder/src/abi-strategy/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './account-abstraction.js'
12
export * from './blockscout-abi.js'
23
export * from './etherscan-abi.js'
34
export * from './etherscanv2-abi.js'

packages/transaction-decoder/src/decoding/calldata-decode.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Effect } from 'effect'
2-
import { Hex, Address, encodeFunctionData, isAddress, getAddress } from 'viem'
2+
import { Hex, Address, encodeFunctionData, isAddress, getAddress, Abi } from 'viem'
33
import { getAndCacheAbi, MissingABIError } from '../abi-loader.js'
44
import * as AbiDecoder from './abi-decode.js'
55
import { TreeNode } from '../types.js'
@@ -8,8 +8,8 @@ import { SAFE_MULTISEND_ABI, SAFE_MULTISEND_SIGNATURE } from './constants.js'
88
import { getProxyImplementation } from './proxies.js'
99
import * as AbiStore from '../abi-store.js'
1010

11-
const callDataKeys = ['callData', 'data', '_data']
12-
const addressKeys = ['to', 'target', '_target']
11+
const callDataKeys = ['callData', 'data', '_data', 'targetCallData']
12+
const addressKeys = ['to', 'target', '_target', 'sender']
1313

1414
const decodeBytesRecursively = (
1515
node: TreeNode,

packages/transaction-decoder/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export interface Tree extends Node {
1919

2020
export interface InputArg extends Node {
2121
value: string | string[]
22-
valueDecoded?: DecodeResult | DecodeResult[]
22+
valueDecoded?: DecodeResult | DecodeResult[] | TreeNode | TreeNode[]
2323
components?: never
2424
}
2525

0 commit comments

Comments
 (0)