From 36bb4c704a516b0524b4000671cd2c4e04ba37c4 Mon Sep 17 00:00:00 2001 From: Gosuto Inzasheru Date: Wed, 28 Jan 2026 13:30:21 +0700 Subject: [PATCH 1/2] fix: bug in safe cli func --- .../brownie/scripts/script_utils.py | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/action-scripts/brownie/scripts/script_utils.py b/action-scripts/brownie/scripts/script_utils.py index e6692d7af..c5dc6f4a0 100644 --- a/action-scripts/brownie/scripts/script_utils.py +++ b/action-scripts/brownie/scripts/script_utils.py @@ -19,6 +19,7 @@ from prettytable import MARKDOWN, PrettyTable from safe_cli.tx_builder.tx_builder_file_decoder import ( encode_contract_method_to_hex_data, + _parse_types_to_encoding_types, ) import safe_cli.tx_builder.tx_builder_file_decoder as decoder_module from safe_eth.eth import EthereumClient @@ -280,8 +281,31 @@ def run_tenderly_sim(network_id: str, safe_addr: str, transactions: list[dict]): address=to_checksum_address(tx["to"]), abi=[tx["contractMethod"]] ) - # Store original parse function + # Store original functions original_parse_func = decoder_module.parse_input_value + original_parse_types_func = decoder_module._parse_types_to_encoding_types + + # Fix for safe_cli bug: _parse_types_to_encoding_types doesn't handle tuple[] correctly + def fixed_parse_types_to_encoding_types(contract_fields): + """Fixed version that correctly handles tuple[] types.""" + types = [] + for field in contract_fields: + field_type = field["type"] + if field_type.startswith("tuple"): + component_types = ",".join( + component["type"] for component in field["components"] + ) + # Preserve array suffix (e.g., "[]" for tuple[]) + suffix = field_type[5:] # Everything after "tuple" + types.append(f"({component_types}){suffix}") + else: + types.append(field_type) + return types + + # Monkey-patch the type parser + decoder_module._parse_types_to_encoding_types = ( + fixed_parse_types_to_encoding_types + ) # Monkey-patch to handle Safe's JSON format with quoted array elements def enhanced_parse_input_value(field_type, value): @@ -373,8 +397,11 @@ def unquote(obj): fn_name=tx["contractMethod"]["name"], args=[] ) finally: - # Restore original function + # Restore original functions decoder_module.parse_input_value = original_parse_func + decoder_module._parse_types_to_encoding_types = ( + original_parse_types_func + ) # build multicall data multisend_call_only = MultiSend.MULTISEND_CALL_ONLY_ADDRESSES[0] From b9ab02ca3cc06215f8edb1709ea1bdd37c959763 Mon Sep 17 00:00:00 2001 From: gosuto-inzasheru <2835259+gosuto-inzasheru@users.noreply.github.com> Date: Wed, 28 Jan 2026 06:54:33 +0000 Subject: [PATCH 2/2] style: ci lint with `black` --- action-scripts/brownie/scripts/script_utils.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/action-scripts/brownie/scripts/script_utils.py b/action-scripts/brownie/scripts/script_utils.py index c5dc6f4a0..0d553e82c 100644 --- a/action-scripts/brownie/scripts/script_utils.py +++ b/action-scripts/brownie/scripts/script_utils.py @@ -406,7 +406,12 @@ def unquote(obj): # build multicall data multisend_call_only = MultiSend.MULTISEND_CALL_ONLY_ADDRESSES[0] txs = [ - MultiSendTx(MultiSendOperation.CALL, to_checksum_address(tx["to"]), int(tx["value"]), tx["data"]) + MultiSendTx( + MultiSendOperation.CALL, + to_checksum_address(tx["to"]), + int(tx["value"]), + tx["data"], + ) for tx in transactions ] data = MultiSend(EthereumClient(web3.provider.endpoint_uri)).build_tx_data(txs)