Skip to content

Commit e46821d

Browse files
author
Dev Kalra
authored
feat(xc_admin_frontend): parse entropy and executor abis (#1481)
* parse entropy and executor abis * correct import * move parse to xc admin frontend * undo change * fix deps * add comment * comment * revert changes and then some minor change * fix unknown by typecast
1 parent 644b546 commit e46821d

File tree

4 files changed

+1318
-10
lines changed

4 files changed

+1318
-10
lines changed

governance/xc_admin/packages/xc_admin_frontend/components/InstructionViews/WormholeInstructionView.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { usePythContext } from '../../contexts/PythContext'
2222
import { getMappingCluster, isPubkey } from './utils'
2323
import { PythCluster } from '@pythnetwork/client'
2424
import { lamportsToSol } from '../../utils/lamportsToSol'
25+
import { parseEvmExecuteCallData } from '../../utils/parseEvmExecuteCallData'
2526

2627
const GovernanceInstructionView = ({
2728
instruction,
@@ -408,16 +409,41 @@ export const WormholeInstructionView = ({
408409
<CopyText text={'0x' + governanceAction.callAddress} />
409410
</div>
410411
<div>Value: {governanceAction.value.toString()}</div>
411-
<div>
412-
Call Data:{' '}
413-
<CopyText
414-
text={'0x' + governanceAction.calldata.toString('hex')}
415-
/>
416-
</div>
412+
<EvmExecuteCallData calldata={governanceAction.calldata} />
417413
</div>
418414
}
419415
/>
420416
)}
421417
</div>
422418
)
423419
}
420+
421+
function EvmExecuteCallData({ calldata }: { calldata: Buffer }) {
422+
const callDataHex = calldata.toString('hex')
423+
const parsedData = parseEvmExecuteCallData(callDataHex)
424+
if (parsedData === undefined)
425+
return (
426+
<div>
427+
Call Data:
428+
<CopyText text={callDataHex} />
429+
</div>
430+
)
431+
432+
return (
433+
<>
434+
<div>Call Method: {parsedData.method}</div>
435+
<div>Call Params: </div>
436+
<div className="mx-4">
437+
{parsedData.inputs.length > 0 ? (
438+
parsedData.inputs.map(([key, value]) => (
439+
<div key={key}>
440+
{key}: {value}
441+
</div>
442+
))
443+
) : (
444+
<div>No params</div>
445+
)}
446+
</div>
447+
</>
448+
)
449+
}

governance/xc_admin/packages/xc_admin_frontend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
"react-hot-toast": "^2.4.0",
3636
"typescript": "4.9.4",
3737
"use-debounce": "^9.0.2",
38-
"xc_admin_common": "*",
39-
"message_buffer": "*"
38+
"web3": "^4.8.0",
39+
"xc_admin_common": "*"
4040
},
4141
"devDependencies": {
4242
"@svgr/webpack": "^6.3.1",
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import Web3 from 'web3'
2+
3+
// Note: Currently, the ABI only contains the functions which take in primitives as inputs.
4+
// Though it is possible for EVM functions to accept structs as one of the inputs.
5+
// We don't support that right now. There is no requirement for that now or in the
6+
// foreseeable future. Adding it now will add unnecessary complexity.
7+
// It will be added when needed.
8+
const ABI = [
9+
{
10+
inputs: [],
11+
name: 'acceptOwnership',
12+
outputs: [],
13+
stateMutability: 'nonpayable',
14+
type: 'function',
15+
},
16+
{
17+
inputs: [],
18+
name: 'acceptAdmin',
19+
outputs: [],
20+
stateMutability: 'nonpayable',
21+
type: 'function',
22+
},
23+
{
24+
inputs: [
25+
{
26+
internalType: 'address',
27+
name: 'newImplementation',
28+
type: 'address',
29+
},
30+
],
31+
name: 'upgradeTo',
32+
outputs: [],
33+
stateMutability: 'nonpayable',
34+
type: 'function',
35+
},
36+
]
37+
38+
type Input = {
39+
internalType: string
40+
name: string
41+
type: string
42+
}
43+
44+
/**
45+
* Parses the call data for an EVM contract call only if the call data matches one of the entry in ABI.
46+
* If there is a match, the method name and inputs are returned. Else, undefined is returned.
47+
* @param callData The call data in hex format.
48+
* @returns The parsed call data or undefined.
49+
*/
50+
export function parseEvmExecuteCallData(callData: string):
51+
| {
52+
method: string
53+
inputs: [string, string][]
54+
}
55+
| undefined {
56+
for (const abi of ABI) {
57+
const web3 = new Web3()
58+
const methodSignature = web3.eth.abi
59+
.encodeFunctionSignature(abi)
60+
.replace('0x', '')
61+
62+
if (!callData.includes(methodSignature)) {
63+
continue
64+
}
65+
66+
const inputs: Input[] = abi.inputs
67+
68+
const decodedParams = web3.eth.abi.decodeParameters(
69+
inputs.map((input) => ({
70+
type: input.type,
71+
name: input.name,
72+
})),
73+
callData.replace(methodSignature, '')
74+
)
75+
return {
76+
method: abi.name,
77+
inputs: inputs.map((input) => [
78+
input.name,
79+
decodedParams[input.name] as string,
80+
]),
81+
}
82+
}
83+
84+
return undefined
85+
}

0 commit comments

Comments
 (0)