Skip to content

Commit 846e2a5

Browse files
committed
US-322: Can now decode scilla logs. (#16)
* (feat) Scilla log decodes now work. * (fix) US-322: Fix package-lock.json
1 parent a41da79 commit 846e2a5

File tree

4 files changed

+136
-28
lines changed

4 files changed

+136
-28
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
"@types/react-highlight": "^0.12.8",
2929
"@types/react-syntax-highlighter": "^15.5.11",
3030
"chart.js": "^4.4.1",
31-
"ethers": "^6.10.0",
3231
"@zilliqa-js/zilliqa" : "^3.5.0",
32+
"ethers": "zilliqa/ethers.js#ethers-zq",
3333
"highlightjs-solidity": "^2.0.6",
3434
"prettier-plugin-organize-imports": "^3.2.4",
3535
"react": "^18.2.0",

src/execution/transaction/LogEntry.tsx

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { RuntimeContext } from "../../useRuntime";
77
import TransactionAddressWithCopy from "../components/TransactionAddressWithCopy";
88
import DecodedLogSignature from "./decoder/DecodedLogSignature";
99
import DecodedParamsTable from "./decoder/DecodedParamsTable";
10+
import DecodedScillaLogSignature from "./decoder/DecodedScillaLogSignature";
11+
import DecodedScillaParamsTable from "./decoder/DecodedScillaParamsTable";
1012
import LogIndex from "./log/LogIndex";
1113
import RawLog from "./log/RawLog";
1214
import TwoColumnPanel from "./log/TwoColumnPanel";
@@ -19,27 +21,65 @@ type LogEntryProps = {
1921
log: Log;
2022
};
2123

24+
type ScillaLog = {
25+
eventName: string;
26+
address: string;
27+
params: object;
28+
};
29+
30+
const EvmLogDisplay: FC<LogDisplayProps> = ( {resolvedLogDesc} ) => {
31+
return ( <div> {resolvedLogDesc === undefined ? (
32+
<TwoColumnPanel>Waiting for data...</TwoColumnPanel>
33+
) : resolvedLogDesc === null ? (
34+
<TwoColumnPanel>Cannot decode data</TwoColumnPanel>
35+
) : (
36+
<TwoColumnPanel>
37+
<DecodedLogSignature event={resolvedLogDesc.fragment} />
38+
<DecodedParamsTable
39+
args={resolvedLogDesc.args}
40+
paramTypes={resolvedLogDesc.fragment.inputs}
41+
hasParamNames={resolvedLogDesc === logDesc || resolvedLogDesc === scillaLogDesc}
42+
/>
43+
</TwoColumnPanel>
44+
)
45+
} </div>);
46+
};
47+
48+
/// Display a scilla log; if the log were null, we would have defaulted to
49+
/// EvmLogDisplay, so no need to handle undefined or null.
50+
const ScillaLogDisplay: FC<ScillaLog> = ( { scillaLogDesc} ) => {
51+
let eventProps = { name: scillaLogDesc.eventName, address: scillaLogDesc.address }
52+
return ( <div> <TwoColumnPanel>
53+
<DecodedScillaLogSignature event={eventProps} />
54+
<DecodedScillaParamsTable params={ scillaLogDesc.params } />
55+
</TwoColumnPanel>
56+
</div>
57+
)
58+
}
59+
60+
61+
2262
const LogEntry: FC<LogEntryProps> = ({ log }) => {
2363
const { provider } = useContext(RuntimeContext);
2464
const match = useSourcifyMetadata(log.address, provider?._network.chainId);
2565

26-
const scillaLogDesc = useMemo(() => {
66+
const scillaLogDesc : ScillaLog | undefined = useMemo(() => {
2767
// Scilla logs are encoded as a single JSON string.
2868
try {
2969
const data = JSON.parse(AbiCoder.defaultAbiCoder().decode(["string"], log.data)[0]);
30-
const params: any[] = data.params;
31-
return new LogDescription(
32-
EventFragment.from({type: "event", name: data._eventname, inputs: params.map(p => ({ name: p.vname, type: p.type }))}),
33-
"",
34-
Result.fromItems(params.map(p => (p.value)), params.map(p=> (p.name)))
35-
);
70+
return {
71+
eventName: data._eventname,
72+
address: data.address,
73+
params: data.params
74+
}
3675
} catch (err) {
3776
// Silently ignore on purpose
3877
return undefined;
3978
}
4079
}, [log]);
4180

42-
const logDesc = useMemo(() => {
81+
const logDesc = scillaLogDesc ? undefined :
82+
useMemo(() => {
4383
if (!match) {
4484
return match;
4585
}
@@ -58,9 +98,9 @@ const LogEntry: FC<LogEntryProps> = ({ log }) => {
5898
}, [log, match]);
5999

60100
const rawTopic0 = log.topics[0];
61-
const topic0 = useTopic0(rawTopic0);
101+
const topic0 = scillaLogDesc ? undefined : useTopic0(rawTopic0);
62102

63-
const topic0LogDesc = useMemo(() => {
103+
const topic0LogDesc = scillaLogDesc ? undefined : useMemo(() => {
64104
if (!topic0) {
65105
return topic0;
66106
}
@@ -84,7 +124,7 @@ const LogEntry: FC<LogEntryProps> = ({ log }) => {
84124
return undefined;
85125
}, [topic0, log]);
86126

87-
const resolvedLogDesc = scillaLogDesc ?? logDesc ?? topic0LogDesc;
127+
const resolvedLogDesc = logDesc ?? topic0LogDesc;
88128

89129
return (
90130
<div className="flex space-x-10 py-5">
@@ -105,22 +145,11 @@ const LogEntry: FC<LogEntryProps> = ({ log }) => {
105145
</TwoColumnPanel>
106146
</Tab.List>
107147
<Tab.Panels as={React.Fragment}>
108-
<Tab.Panel>
109-
{resolvedLogDesc === undefined ? (
110-
<TwoColumnPanel>Waiting for data...</TwoColumnPanel>
111-
) : resolvedLogDesc === null ? (
112-
<TwoColumnPanel>Can't decode data</TwoColumnPanel>
113-
) : (
114-
<TwoColumnPanel>
115-
<DecodedLogSignature event={resolvedLogDesc.fragment} />
116-
<DecodedParamsTable
117-
args={resolvedLogDesc.args}
118-
paramTypes={resolvedLogDesc.fragment.inputs}
119-
hasParamNames={resolvedLogDesc === logDesc || resolvedLogDesc === scillaLogDesc}
120-
/>
121-
</TwoColumnPanel>
122-
)}
123-
</Tab.Panel>
148+
<Tab.Panel>
149+
({ scillaLogDesc !== undefined && scillaLogDesc !== null ?
150+
<ScillaLogDisplay scillaLogDesc={scillaLogDesc} /> :
151+
<EvmLogDisplay resolvedLogDesc={resolvedLogDesc} />})
152+
</Tab.Panel>
124153
<Tab.Panel as={React.Fragment}>
125154
<RawLog topics={log.topics} data={log.data} />
126155
</Tab.Panel>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { EventFragment } from "ethers";
2+
import { FC, memo } from "react";
3+
4+
type DecodedScillaLogSignatureProps = {
5+
name: string;
6+
address: string;
7+
};
8+
9+
const DecodedScillaLogSignature: FC<DecodedScillaLogSignatureProps> = ({ event }) => {
10+
if (event) {
11+
return (
12+
<span className="font-mono">
13+
<span className="font-italic">_eventName:</span> <span className="font-bold text-blue-900">{event.name}</span><br/>
14+
<span className="font-italic">address:</span> <span className="font-bold text-blue-500">{event.address}</span><br/>
15+
</span>)
16+
} else {
17+
return ( <div /> )
18+
}
19+
}
20+
21+
export default memo(DecodedScillaLogSignature);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { ParamType, Result } from "ethers";
2+
import { FC, memo } from "react";
3+
import { DevMethod, UserMethod } from "../../../sourcify/useSourcify";
4+
import DecodedParamRow from "./DecodedParamRow";
5+
6+
type DecodedScillaParamsTableProps = {
7+
params: object;
8+
};
9+
10+
type DecodedScillaParamRowProps = {
11+
name: string;
12+
valueType: string;
13+
value: string;
14+
};
15+
16+
const DecodedScillaParamRow: FC<DecodedScillaParamRowProps> = ({
17+
name,
18+
valueType,
19+
value }) => {
20+
return (
21+
<>
22+
<tr className="grid grid-cols-12 gap-x-2 py-2 hover:bg-gray-100">
23+
<td className="col-span-3 pl-1">
24+
<span className="text-gray-600">{name}</span>
25+
</td>
26+
<td className="col-span-1 text-gray-500">{valueType}</td>
27+
<td className="col-span-8 text-gray-500">{value}</td>
28+
</tr>
29+
</>
30+
)};
31+
32+
33+
const DecodedScillaParamsTable: FC<DecodedScillaParamsTableProps> = ({
34+
params } ) => {
35+
// params.map((val) => { alert(`X ${JSON.stringify(val)}`) });
36+
return (
37+
<table className="w-full border">
38+
<thead>
39+
<tr className="grid grid-cols-12 gap-x-2 bg-gray-100 py-2 text-left">
40+
<th className="col-span-3 pl-1">
41+
name
42+
</th>
43+
<th className="col-span-1 pl-1">
44+
type
45+
</th>
46+
<th className="col-span-8 pr-1">value</th>
47+
</tr>
48+
</thead>
49+
<tbody className="divide-y">
50+
{params.map((val) => (
51+
<DecodedScillaParamRow name={val["vname"]} valueType={val["type"]} value={val["value"]} />
52+
))}
53+
</tbody>
54+
</table>
55+
);
56+
}
57+
58+
export default memo(DecodedScillaParamsTable);

0 commit comments

Comments
 (0)