diff --git a/libs/moloch-v3-macro-ui/src/components/ProposalActionData/ProposalActionData.tsx b/libs/moloch-v3-macro-ui/src/components/ProposalActionData/ProposalActionData.tsx
index b83bfb86..45575792 100644
--- a/libs/moloch-v3-macro-ui/src/components/ProposalActionData/ProposalActionData.tsx
+++ b/libs/moloch-v3-macro-ui/src/components/ProposalActionData/ProposalActionData.tsx
@@ -1,5 +1,5 @@
import { ReactNode, useState } from 'react';
-import { isValidNetwork } from '@daohaus/keychain-utils';
+import { ValidNetwork, isValidNetwork } from '@daohaus/keychain-utils';
import { MolochV3Proposal } from '@daohaus/moloch-v3-data';
import {
ActionError,
@@ -18,6 +18,7 @@ import {
useBreakpoint,
widthQuery,
ParLg,
+ DataMd,
} from '@daohaus/ui';
import {
DAO_METHOD_TO_PROPOSAL_TYPE,
@@ -210,20 +211,52 @@ const ActionToggle = ({
const ActionSectionError = ({
action,
+ actionHeader,
+ daoChain,
index,
+ isMobile,
}: {
action: ActionError;
+ actionHeader: string;
+ daoChain?: ValidNetwork;
index: number;
+ isMobile?: boolean;
}) => {
return (
-
Action {index + 1}: Error
-
{action.message}
-
-
- HEX DATA:
-
-
{action.data}
+
+ <>
+ Action {index + 1}
+ Error: {action.message}
+
+ {action.contractAddress && (
+ <>
+
+ TARGET
+
+
+ >
+ )}
+
+ HEX DATA:
+
+ {action.data}
+ {action.value && (
+ <>
+
+ VALUE
+
+ {action.value}
+ >
+ )}
+ >
+
);
};
@@ -249,7 +282,15 @@ const ActionSection = ({
const isMobile = useBreakpoint(widthQuery.sm);
if (isActionError(action)) {
- return ;
+ return (
+
+ );
}
return (
diff --git a/libs/tx-builder/src/utils/decoding.ts b/libs/tx-builder/src/utils/decoding.ts
index 23b97e23..cbdd546a 100644
--- a/libs/tx-builder/src/utils/decoding.ts
+++ b/libs/tx-builder/src/utils/decoding.ts
@@ -16,6 +16,8 @@ export type ActionError = {
error: boolean;
message: string;
data: string;
+ contractAddress?: string;
+ value?: string;
};
export type DecodedMultiTX = (DecodedAction | ActionError)[];
diff --git a/libs/tx-builder/src/utils/deepDecoding.ts b/libs/tx-builder/src/utils/deepDecoding.ts
index d1583f1d..ec0fc34b 100644
--- a/libs/tx-builder/src/utils/deepDecoding.ts
+++ b/libs/tx-builder/src/utils/deepDecoding.ts
@@ -88,10 +88,17 @@ export const deepDecodeProposalActions = async ({
return decodeMultiCall(options, actionData as `0x${string}`);
};
-const createActionError = (data: string, message: string): ActionError => ({
+const createActionError = (
+ data: string,
+ message: string,
+ contractAddress?: string,
+ value?: string
+): ActionError => ({
error: true,
message,
data,
+ contractAddress,
+ value,
});
const decodeMultiCall = async (
@@ -192,7 +199,8 @@ const actionDecoders: Record<
) {
return createActionError(
action.data,
- 'Could not decode action: multiSend'
+ 'Could not decode action: multiSend',
+ action.to
);
}
const input = decodedMethod.inputs[0];
@@ -200,7 +208,8 @@ const actionDecoders: Record<
if (input.type !== 'bytes') {
return createActionError(
action.data,
- 'Could not decode action: multiSend'
+ 'Could not decode action: multiSend',
+ action.to
);
}
@@ -227,7 +236,8 @@ const actionDecoders: Record<
) {
return createActionError(
action.data,
- 'Could not decode action: execTransactionFromModule'
+ 'Could not decode action: execTransactionFromModule',
+ action.to
);
}
const inputTo = decodedMethod.inputs[0];
@@ -243,7 +253,8 @@ const actionDecoders: Record<
) {
return createActionError(
action.data,
- 'Could not decode action: execTransactionFromModule'
+ 'Could not decode action: execTransactionFromModule',
+ action.to
);
}
@@ -274,7 +285,8 @@ const actionDecoders: Record<
) {
return createActionError(
action.data,
- 'Could not decode action: executeAsBaal'
+ 'Could not decode action: executeAsBaal',
+ action.to
);
}
const inputTo = decodedMethod.inputs[0];
@@ -288,7 +300,8 @@ const actionDecoders: Record<
) {
return createActionError(
action.data,
- 'Could not decode action: executeAsBaal'
+ 'Could not decode action: executeAsBaal',
+ action.to
);
}
@@ -349,7 +362,8 @@ const actionDecoders: Record<
) {
return createActionError(
action.data,
- 'Could not decode action: multiSend'
+ 'Could not decode action: multiSend',
+ action.to
);
}
const input = decodedMethod.inputs[0];
@@ -357,7 +371,8 @@ const actionDecoders: Record<
if (input.type !== 'bytes[]') {
return createActionError(
action.data,
- 'Could not decode action: multicall'
+ 'Could not decode action: multicall',
+ action.to
);
}
@@ -420,7 +435,12 @@ const decodeAction = async (
});
if (!abi || !abi?.length) {
- return createActionError(data, 'Could not decode action: abi not found');
+ return createActionError(
+ data,
+ 'Could not decode action: abi not found',
+ to,
+ decodeValue(value)
+ );
}
const decodedMethod = decodeMethod({
@@ -429,7 +449,12 @@ const decodeAction = async (
});
if (!decodedMethod) {
- return createActionError(data, 'Could not decode action: method not found');
+ return createActionError(
+ data,
+ 'Could not decode action: method not found',
+ to,
+ decodeValue(value)
+ );
}
const methodSignature = data.slice(0, 10);
diff --git a/libs/tx-builder/src/utils/multicall.ts b/libs/tx-builder/src/utils/multicall.ts
index 850894ae..6e775587 100644
--- a/libs/tx-builder/src/utils/multicall.ts
+++ b/libs/tx-builder/src/utils/multicall.ts
@@ -169,8 +169,13 @@ const handleMulticallFormActions = ({
if (!validTxs.length) {
throw new Error('No actions found');
}
- // TODO: sort by tx.actionId.index
- return validTxs.map((actionId: string) => {
+ const sortedTxs = validTxs.sort((actionA: string, actionB: string) =>
+ Number(appState.formValues.tx[actionA].index) >
+ Number(appState.formValues.tx[actionB].index)
+ ? 1
+ : -1
+ );
+ return sortedTxs.map((actionId: string) => {
const action = appState.formValues.tx[actionId];
const { to, data, value, operation } = action;
return {