Skip to content

Commit 951f28b

Browse files
authored
Merge pull request #2447 from AmbireTech/fixes/clear-signing-cases
Fixes/clear signing cases
2 parents 895c909 + e1409f8 commit 951f28b

4 files changed

Lines changed: 577 additions & 29 deletions

File tree

src/libs/humanizer/erc7730/humanize.ts

Lines changed: 120 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ import { Message } from '../../../interfaces/userRequest'
1414
import { AccountOp } from '../../accountOp/accountOp'
1515
import { Call } from '../../accountOp/types'
1616
import {
17+
HumanizerCallModule,
1718
HumanizerErc7730Row,
1819
HumanizerErc7730Visualization,
19-
HumanizerCallModule,
2020
HumanizerMeta,
2121
HumanizerVisualization,
2222
HumanizerWarning,
2323
IrCall,
2424
IrMessage
2525
} from '../interfaces'
26-
import AllowanceModule, { getSetAllowanceResetText } from '../modules/Allowance'
2726
import { aaveHumanizer } from '../modules/Aave'
27+
import AllowanceModule, { getSetAllowanceResetText } from '../modules/Allowance'
2828
import { decodeGeneralAdapterCall } from '../modules/Bundler3/generalAdapter'
2929
import { getDelegateCallWarning, getSafeHumanization } from '../modules/Safe'
3030
import { genericErc20Humanizer } from '../modules/Tokens'
@@ -34,9 +34,9 @@ import {
3434
getChain,
3535
getErc7730Visualization,
3636
getText,
37-
getToken
37+
getToken,
38+
uintToAddress
3839
} from '../utils'
39-
import { getAbiBytesCalldataWithPadding, multiSendInterface } from './calldata'
4040
import { SAFE_TX_PRIMARY_TYPE } from './consts'
4141
import { getEip712EncodeType, getEip712EncodeTypeHashFromString } from './eip712'
4242
import {
@@ -71,6 +71,7 @@ type VisibilityResult = {
7171

7272
const MAX_INTERPOLATED_VALUE_LENGTH = 80
7373
const MAX_NESTED_CALLDATA_DEPTH = 4
74+
const ABI_WORD_HEX_LENGTH = 64
7475

7576
const isMapReference = (value: unknown): value is Erc7730MapReference =>
7677
isPlainObject(value) && typeof value.map === 'string' && typeof value.keyPath === 'string'
@@ -129,6 +130,15 @@ const getPathSegments = (path: string): string[] => {
129130
const normalizeSegmentIndex = (index: number, length: number): number =>
130131
index < 0 ? length + index : index
131132

133+
const bigintToAbiWordHex = (value: bigint): string | null => {
134+
if (value < 0n) return null
135+
136+
const hex = value.toString(16)
137+
if (hex.length > ABI_WORD_HEX_LENGTH) return null
138+
139+
return hex.padStart(ABI_WORD_HEX_LENGTH, '0')
140+
}
141+
132142
const readBracketSegment = (source: unknown, segment: string): unknown => {
133143
if (!segment.startsWith('[') || !segment.endsWith(']')) return undefined
134144

@@ -143,9 +153,17 @@ const readBracketSegment = (source: unknown, segment: string): unknown => {
143153
}
144154

145155
if (separatorIndex === bracketContent.lastIndexOf(':')) {
146-
if (typeof source !== 'string') return undefined
156+
const hex =
157+
typeof source === 'string'
158+
? source.startsWith('0x')
159+
? source.slice(2)
160+
: source
161+
: typeof source === 'bigint'
162+
? bigintToAbiWordHex(source)
163+
: null
164+
165+
if (hex === null) return undefined
147166

148-
const hex = source.startsWith('0x') ? source.slice(2) : source
149167
if (hex.length % 2 !== 0) return undefined
150168

151169
const startText = bracketContent.slice(0, separatorIndex)
@@ -483,6 +501,15 @@ const getTokenAddressFromField = (
483501
const tokenAddress = tokenPath ?? tokenParam
484502

485503
if (hasTokenSource && isNativeTokenReference(tokenAddress)) return ZeroAddress
504+
if (typeof tokenAddress === 'bigint') {
505+
const uintAddress = uintToAddress(tokenAddress)
506+
507+
return nativeAddresses.some(
508+
(address) => eToNative(address).toLowerCase() === eToNative(uintAddress).toLowerCase()
509+
)
510+
? ZeroAddress
511+
: eToNative(uintAddress)
512+
}
486513
if (typeof tokenAddress !== 'string' || !isAddress(tokenAddress)) return null
487514

488515
return nativeAddresses.some(
@@ -521,7 +548,9 @@ const getEnumValue = (
521548
if (!isPlainObject(enumDefinition)) return null
522549

523550
const values = isPlainObject(enumDefinition.values) ? enumDefinition.values : enumDefinition
524-
const enumValue = values[valueToText(value)]
551+
const enumKey =
552+
typeof value === 'string' && isHexString(value) ? toBigIntOrNull(value)?.toString() : undefined
553+
const enumValue = values[enumKey || valueToText(value)]
525554

526555
return typeof enumValue === 'string' ? enumValue : null
527556
}
@@ -533,6 +562,8 @@ const formatFieldValue = (
533562
base: unknown
534563
): HumanizerVisualization[] => {
535564
if (field.format === 'addressName' || field.format === 'interoperableAddressName') {
565+
if (typeof value === 'bigint') return [getAddressVisualization(uintToAddress(value))]
566+
536567
return typeof value === 'string' && isAddress(value)
537568
? [getAddressVisualization(value)]
538569
: [getText(valueToText(value))]
@@ -670,7 +701,7 @@ const getCalldataRows = (
670701
const amountValues = resolveCalldataParam(field, context, base, 'amountPath', 'amount')
671702
const accountAddr = resolvePath('#.@.accountAddr', context, context.root)
672703
const nestedRowLabel =
673-
field.label?.trim().toLowerCase() === 'call' ? '' : field.label ?? field.path ?? ''
704+
field.label?.trim().toLowerCase() === 'call' ? '' : (field.label ?? field.path ?? '')
674705

675706
return values.reduce<HumanizerErc7730Row[] | null>((acc, calldata, index) => {
676707
if (!acc) return null
@@ -875,6 +906,76 @@ const formatToVisualizations = (
875906
return [getErc7730Visualization(intent, rows, dapp)]
876907
}
877908

909+
const isOneInchFillOrderFormat = (formatKey: string, descriptorPath?: string) =>
910+
!!descriptorPath?.includes('registry/1inch/') && formatKey.startsWith('fillOrder(')
911+
912+
const getUintAddressValue = (value: unknown): string | null => {
913+
if (typeof value === 'bigint') return uintToAddress(value)
914+
if (typeof value === 'string' && isAddress(value)) return value
915+
916+
return null
917+
}
918+
919+
const getOneInchFillOrderSwapVisualization = (
920+
match: DescriptorFormatMatch,
921+
context: FormatContext,
922+
fullVisualization: HumanizerVisualization[],
923+
dapp?: Call['dapp']
924+
): HumanizerVisualization[] | null => {
925+
if (!isOneInchFillOrderFormat(match.formatKey, context.descriptorPath)) return fullVisualization
926+
927+
const order = match.values.order
928+
if (!isPlainObject(order)) return fullVisualization
929+
930+
const maker = getUintAddressValue(order.maker)
931+
const makerAsset = getUintAddressValue(order.makerAsset)
932+
const takerAsset = getUintAddressValue(order.takerAsset)
933+
const makingAmount = toBigIntOrNull(order.makingAmount)
934+
const takingAmount = toBigIntOrNull(order.takingAmount)
935+
936+
if (!maker || !makerAsset || !takerAsset || makingAmount === null || takingAmount === null) {
937+
return fullVisualization
938+
}
939+
940+
const metadata = context.root['@']
941+
const accountAddr = isPlainObject(metadata) ? metadata.accountAddr : undefined
942+
const isMakerAccount =
943+
typeof accountAddr === 'string' && maker.toLowerCase() === accountAddr.toLowerCase()
944+
const outgoingToken = isMakerAccount ? makerAsset : takerAsset
945+
const outgoingAmount = isMakerAccount ? makingAmount : toBigIntOrNull(match.values.amount)
946+
const incomingToken = isMakerAccount ? takerAsset : makerAsset
947+
const incomingAmount = isMakerAccount ? takingAmount : makingAmount
948+
949+
if (outgoingAmount === null) return fullVisualization
950+
951+
const oneInchVisualization = fullVisualization.find(
952+
(visualization): visualization is HumanizerVisualization & HumanizerErc7730Visualization =>
953+
visualization.type === 'erc7730'
954+
)
955+
const additionalRows =
956+
oneInchVisualization?.rows.filter(
957+
(row) => !row.value.some((value) => value.type === 'token')
958+
) || []
959+
960+
return [
961+
getErc7730Visualization(
962+
oneInchVisualization?.title || 'Fill order',
963+
[
964+
{
965+
label: 'Amount to Send',
966+
value: [getToken(outgoingToken, outgoingAmount, context.chainId)]
967+
},
968+
{
969+
label: 'Minimum to Receive',
970+
value: [getToken(incomingToken, incomingAmount, context.chainId)]
971+
},
972+
...additionalRows
973+
],
974+
dapp
975+
)
976+
]
977+
}
978+
878979
const getSafeTxCallFromMessage = (message: Message): Call | null => {
879980
if (message.content.kind !== 'typedMessage') return null
880981
if (message.content.primaryType !== SAFE_TX_PRIMARY_TYPE) return null
@@ -1005,14 +1106,12 @@ const getSafeCallFallbackVisualization = (
10051106
? { ...visualization, content: String(visualization.content) }
10061107
: visualization
10071108
)
1008-
const rows: HumanizerErc7730Row[] = value.length
1009-
? [
1010-
{
1011-
label: action.content,
1012-
value
1013-
}
1014-
]
1015-
: []
1109+
const rows: HumanizerErc7730Row[] = [
1110+
{
1111+
label: action.content,
1112+
value: value.length || !call.to ? value : [getAddressVisualization(call.to)]
1113+
}
1114+
]
10161115
if (!rows.length) return null
10171116

10181117
const visualization = getErc7730Visualization(action.content, rows)
@@ -1285,11 +1384,14 @@ export const humanizeCallWithErc7730 = (
12851384
nestedCalldataDepth
12861385
}
12871386
const fullVisualization = formatToVisualizations(match.format, context, call.dapp)
1387+
const normalizedVisualization = fullVisualization
1388+
? getOneInchFillOrderSwapVisualization(match, context, fullVisualization, call.dapp)
1389+
: null
12881390

1289-
return fullVisualization?.length
1391+
return normalizedVisualization?.length
12901392
? {
12911393
...call,
1292-
fullVisualization,
1394+
fullVisualization: normalizedVisualization,
12931395
warnings: dedupeWarnings(getSafeCallWarnings(call, accountAddr))
12941396
}
12951397
: null

0 commit comments

Comments
 (0)