diff --git a/.github/workflows/build_and_functional_tests.yml b/.github/workflows/build_and_functional_tests.yml index 508a7a6cf..c122a4fc1 100644 --- a/.github/workflows/build_and_functional_tests.yml +++ b/.github/workflows/build_and_functional_tests.yml @@ -61,3 +61,21 @@ jobs: additional_app_binaries_artifact_dir: ./tests/ragger/.test_dependencies/clone/build/ test_options: "--setup lib_mode" regenerate_snapshots: ${{ inputs.golden_run == 'Open a PR' }} + + build_mem_app: + name: Build Memory application using the reusable workflow + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_build.yml@v1 + with: + upload_app_binaries_artifact: "memory_elfs" + flags: "memory_profiling" + run_for_devices: '["nanox"]' + + ragger_mem_tests: + name: Run Memory tests using the reusable workflow + needs: build_application + uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_ragger_tests.yml@v1 + with: + download_app_binaries_artifact: "memory_elfs" + test_options: " -s 2>&1 | tools/valground.py -q" + run_for_devices: '["nanox"]' + upload_snapshots_on_failure: false diff --git a/CHANGELOG.md b/CHANGELOG.md index ebd4057c3..7dda758a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.19.0](../../compare/1.18.1...1.19.0) - 2025-xx-xx + ## [1.18.1](../../compare/1.18.0...1.18.1) - 2025-08-27 ### Fixed diff --git a/Makefile b/Makefile index cd4512045..5e7105d05 100644 --- a/Makefile +++ b/Makefile @@ -36,23 +36,23 @@ endif include ./makefile_conf/chain/$(CHAIN).mk APPVERSION_M = 1 -APPVERSION_N = 18 -APPVERSION_P = 1 -APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) +APPVERSION_N = 19 +APPVERSION_P = 0 +APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-dev # Application source files APP_SOURCE_PATH += src src_features src_plugins src_nbgl APP_SOURCE_FILES += $(filter-out ./ethereum-plugin-sdk/src/main.c, $(wildcard ./ethereum-plugin-sdk/src/*.c)) INCLUDES_PATH += ./ethereum-plugin-sdk/src -ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX)) -NETWORK_ICONS_FILE = $(GEN_SRC_DIR)/net_icons.gen.c -NETWORK_ICONS_DIR = $(shell dirname "$(NETWORK_ICONS_FILE)") +ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX TARGET_APEX_M TARGET_APEX_P)) + NETWORK_ICONS_FILE = $(GEN_SRC_DIR)/net_icons.gen.c + NETWORK_ICONS_DIR = $(shell dirname "$(NETWORK_ICONS_FILE)") -$(NETWORK_ICONS_FILE): - $(shell python3 tools/gen_networks.py "$(NETWORK_ICONS_DIR)") + $(NETWORK_ICONS_FILE): + $(shell python3 tools/gen_networks.py "$(NETWORK_ICONS_DIR)") -APP_SOURCE_FILES += $(NETWORK_ICONS_FILE) + APP_SOURCE_FILES += $(NETWORK_ICONS_FILE) endif # Application icons following guidelines: @@ -61,21 +61,25 @@ ICON_NANOX = icons/nanox_app_chain_$(CHAIN_ID).gif ICON_NANOSP = icons/nanox_app_chain_$(CHAIN_ID).gif ICON_STAX = icons/stax_app_chain_$(CHAIN_ID).gif ICON_FLEX = icons/flex_app_chain_$(CHAIN_ID).gif +ICON_APEX_M = icons/apex_app_chain_$(CHAIN_ID).gif +ICON_APEX_P = icons/apex_app_chain_$(CHAIN_ID).gif #prepare hsm generation ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX)) DEFINES += ICONGLYPH=C_chain_$(CHAIN_ID)_64px DEFINES += ICONBITMAP=C_chain_$(CHAIN_ID)_64px_bitmap DEFINES += ICONHOME=C_chain_$(CHAIN_ID)_64px -else -ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_NANOS2)) +else ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME), TARGET_APEX_M TARGET_APEX_P)) + DEFINES += ICONGLYPH=C_chain_$(CHAIN_ID)_48px + DEFINES += ICONBITMAP=C_chain_$(CHAIN_ID)_48px_bitmap + DEFINES += ICONHOME=C_chain_$(CHAIN_ID)_48px +else ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_NANOS2)) DEFINES += ICONGLYPH=C_chain_$(CHAIN_ID)_14px DEFINES += ICONBITMAP=C_chain_$(CHAIN_ID)_14px_bitmap ICON_HOME_NANO = glyphs/home_chain_$(CHAIN_ID)_14px.gif DEFINES += ICONHOME=C_home_chain_$(CHAIN_ID)_14px endif -endif # Don't define plugin function in the plugin SDK DEFINES += IS_NOT_A_PLUGIN diff --git a/README.md b/README.md index 1621f0d90..c090a99a6 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ ## About the project -Ethereum wallet application framework for Ledger Nano S, Ledger Nano S Plus, Ledger Nano X, Ledger Flex and Ledger Stax. +Ethereum wallet application framework for Ledger devices. Ledger Blue is not maintained anymore, but the app can still be compiled for this target using the branch [`blue-final-release`](https://github.com/LedgerHQ/app-ethereum/tree/blue-final-release). ## Documentation @@ -54,9 +54,7 @@ To compile it and load it on a device, please check out our [developer portal](h We have the concept of plugins in the ETH app. Find the documentations here: -- [Blog Ethereum plugins](https://blog.ledger.com/ethereum-plugins/) -- [Ethereum application Plugins : Technical Specifications](https://github.com/LedgerHQ/app-ethereum/blob/master/doc/ethapp_plugins.asc) -- [Plugin guide](https://hackmd.io/300Ukv5gSbCbVcp3cZuwRQ) +- [Plugin guide](https://ethereum-plugin-sdk.ledger.com) - [Boilerplate plugin](https://github.com/LedgerHQ/app-plugin-boilerplate) ## Quick start guide @@ -153,6 +151,8 @@ You can choose which device to compile and load for by setting the `BOLOS_SDK` e - `BOLOS_SDK=$NANOX_SDK` - `BOLOS_SDK=$NANOSP_SDK` - `BOLOS_SDK=$STAX_SDK` +- `BOLOS_SDK=$FLEX_SDK` +- `BOLOS_SDK=$APEX_P_SDK` ### Loading on a physical device diff --git a/client/CHANGELOG.md b/client/CHANGELOG.md index 8c08e88ef..9ff0ea51d 100644 --- a/client/CHANGELOG.md +++ b/client/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.6.0] - 2025-09-05 + +### Added + +- Support for Apex devices + ## [0.5.0] - 2025-06-30 ### Added diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index bd8e1d422..1c7eacea2 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -18,6 +18,7 @@ from .status_word import StatusWord from .ledger_pki import PKIClient, PKIPubKeyUsage from .dynamic_networks import DynamicNetwork +from .safe import SafeAccount, AccountType class TrustedNameType(IntEnum): @@ -35,6 +36,12 @@ class TrustedNameSource(IntEnum): DNS = 0x05 +class EIP712CalldataParamPresence(IntEnum): + NONE = 0x00 + PRESENT_FILTERED = 0x01 + PRESENT_VERIFYING_CONTRACT = 0x02 + + class SignMode(IntEnum): BASIC = 0x00 STORE = 0x01 @@ -51,7 +58,7 @@ def __init__(self, backend: BackendInterface): def _exchange_async(self, payload: bytes): return self._backend.exchange_async_raw(payload) - def _exchange(self, payload: bytes): + def _exchange(self, payload: bytes) -> RAPDU: return self._backend.exchange_raw(payload) def response(self) -> Optional[RAPDU]: @@ -154,6 +161,60 @@ def eip712_filtering_trusted_name(self, sig, discarded)) + def eip712_filtering_calldata_info(self, + index: int, + value_filter_flag: bool, + callee_filter_flag: int, + chain_id_filter_flag: bool, + selector_filter_flag: bool, + amount_filter_flag: bool, + spender_filter_flag: int, + sig: bytes): + return self._exchange(self._cmd_builder.eip712_filtering_calldata_info(index, + value_filter_flag, + callee_filter_flag, + chain_id_filter_flag, + selector_filter_flag, + amount_filter_flag, + spender_filter_flag, + sig)) + + def eip712_filtering_calldata_value(self, + index: int, + sig: bytes, + discarded: bool): + return self._exchange(self._cmd_builder.eip712_filtering_calldata_value(index, sig, discarded)) + + def eip712_filtering_calldata_callee(self, + index: int, + sig: bytes, + discarded: bool): + return self._exchange(self._cmd_builder.eip712_filtering_calldata_callee(index, sig, discarded)) + + def eip712_filtering_calldata_chain_id(self, + index: int, + sig: bytes, + discarded: bool): + return self._exchange(self._cmd_builder.eip712_filtering_calldata_chain_id(index, sig, discarded)) + + def eip712_filtering_calldata_selector(self, + index: int, + sig: bytes, + discarded: bool): + return self._exchange(self._cmd_builder.eip712_filtering_calldata_selector(index, sig, discarded)) + + def eip712_filtering_calldata_amount(self, + index: int, + sig: bytes, + discarded: bool): + return self._exchange(self._cmd_builder.eip712_filtering_calldata_amount(index, sig, discarded)) + + def eip712_filtering_calldata_spender(self, + index: int, + sig: bytes, + discarded: bool): + return self._exchange(self._cmd_builder.eip712_filtering_calldata_spender(index, sig, discarded)) + def eip712_filtering_raw(self, name: str, sig: bytes, discarded: bool): return self._exchange_async(self._cmd_builder.eip712_filtering_raw(name, sig, discarded)) @@ -175,16 +236,19 @@ def serialize_tx(self, tx_params: dict) -> tuple[bytes, bytes]: return encoded_tx, tx_hash def sign(self, - bip32_path: str, - tx_params: dict, + bip32_path: Optional[str] = None, + tx_params: Optional[dict] = None, mode: SignMode = SignMode.BASIC): - tx, _ = self.serialize_tx(tx_params) - chunks = self._cmd_builder.sign(bip32_path, tx, mode) + if tx_params is None: + tx = None + else: + tx, _ = self.serialize_tx(tx_params) + chunks = self._cmd_builder.sign(mode, bip32_path, tx) for chunk in chunks[:-1]: self._exchange(chunk) return self._exchange_async(chunks[-1]) - def get_challenge(self): + def get_challenge(self) -> RAPDU: return self._exchange(self._cmd_builder.get_challenge()) def get_public_addr(self, @@ -420,6 +484,12 @@ def provide_transaction_info(self, payload: bytes) -> RAPDU: self._exchange(chunk) return self._exchange(chunks[-1]) + def provide_transaction_field_desc(self, payload: bytes) -> RAPDU: + chunks = self._cmd_builder.provide_transaction_field_desc(payload) + for chunk in chunks[:-1]: + self._exchange(chunk) + return self._exchange(chunks[-1]) + def opt_in_tx_simulation(self): return self._exchange_async(self._cmd_builder.opt_in_tx_simulation()) @@ -454,3 +524,13 @@ def sign_eip7702_authorization(self, bip32_path: str, auth_params: TxAuth7702): for chunk in chunks[:-1]: self._exchange(chunk) return self._exchange_async(chunks[-1]) + + def provide_safe_account(self, safe_params: SafeAccount): + # Send ledgerPKI certificate - only for SAFE accounts + if safe_params.account_type == AccountType.SAFE: + self.pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_SAFE_ACCOUNT) + + chunks = self._cmd_builder.provide_safe_account(safe_params.serialize(), safe_params.account_type) + for chunk in chunks[:-1]: + self._exchange(chunk) + return self._exchange_async(chunks[-1]) diff --git a/client/src/ledger_app_clients/ethereum/command_builder.py b/client/src/ledger_app_clients/ethereum/command_builder.py index c42fdc8b2..1467efe1f 100644 --- a/client/src/ledger_app_clients/ethereum/command_builder.py +++ b/client/src/ledger_app_clients/ethereum/command_builder.py @@ -29,10 +29,12 @@ class InsType(IntEnum): PROVIDE_TRUSTED_NAME = 0x22 PROVIDE_ENUM_VALUE = 0x24 PROVIDE_TRANSACTION_INFO = 0x26 + PROVIDE_TRANSACTION_FIELD_DESC = 0x28 PROVIDE_PROXY_INFO = 0x2a PROVIDE_NETWORK_INFORMATION = 0x30 PROVIDE_TX_SIMULATION = 0x32 SIGN_EIP7702_AUTHORIZATION = 0x34 + PROVIDE_SAFE_ACCOUNT = 0x36 class P1Type(IntEnum): @@ -54,6 +56,13 @@ class P2Type(IntEnum): FILTERING_ACTIVATE = 0x00 FILTERING_DISCARDED_PATH = 0x01 FILTERING_MESSAGE_INFO = 0x0f + FILTERING_CALLDATA_SPENDER = 0xf4 + FILTERING_CALLDATA_AMOUNT = 0xf5 + FILTERING_CALLDATA_SELECTOR = 0xf6 + FILTERING_CALLDATA_CHAIN_ID = 0xf7 + FILTERING_CALLDATA_CALLEE = 0xf8 + FILTERING_CALLDATA_VALUE = 0xf9 + FILTERING_CALLDATA_INFO = 0xfa FILTERING_TRUSTED_NAME = 0xfb FILTERING_DATETIME = 0xfc FILTERING_TOKEN_ADDR_CHECK = 0xfd @@ -144,8 +153,7 @@ def eip712_send_struct_impl_struct_field(self, data: bytearray) -> list[bytes]: chunks = [] # Add a 16-bit integer with the data's byte length (network byte order) data_w_length = bytearray() - data_w_length.append((len(data) & 0xff00) >> 8) - data_w_length.append(len(data) & 0x00ff) + data_w_length += struct.pack(">H", len(data)) data_w_length += data while len(data_w_length) > 0: p1 = P1Type.PARTIAL_SEND if len(data_w_length) > 0xff else P1Type.COMPLETE_SEND @@ -260,6 +268,108 @@ def eip712_filtering_trusted_name(self, P2Type.FILTERING_TRUSTED_NAME, data) + def eip712_filtering_calldata_info(self, + index: int, + value_filter_flag: bool, + callee_filter_flag: int, + chain_id_filter_flag: bool, + selector_filter_flag: bool, + amount_filter_flag: bool, + spender_filter_flag: int, + sig: bytes) -> bytes: + data = bytearray() + data += struct.pack(">B", index) + data += struct.pack(">B", value_filter_flag) + data += struct.pack(">?", callee_filter_flag) + data += struct.pack(">B", chain_id_filter_flag) + data += struct.pack(">B", selector_filter_flag) + data += struct.pack(">B", amount_filter_flag) + data += struct.pack(">?", spender_filter_flag) + data.append(len(sig)) + data += sig + return self._serialize(InsType.EIP712_SEND_FILTERING, + int(False), + P2Type.FILTERING_CALLDATA_INFO, + data) + + def eip712_filtering_calldata_value(self, + index: int, + sig: bytes, + discarded: bool): + data = bytearray() + data += struct.pack(">B", index) + data.append(len(sig)) + data += sig + return self._serialize(InsType.EIP712_SEND_FILTERING, + int(discarded), + P2Type.FILTERING_CALLDATA_VALUE, + data) + + def eip712_filtering_calldata_callee(self, + index: int, + sig: bytes, + discarded: bool): + data = bytearray() + data += struct.pack(">B", index) + data.append(len(sig)) + data += sig + return self._serialize(InsType.EIP712_SEND_FILTERING, + int(discarded), + P2Type.FILTERING_CALLDATA_CALLEE, + data) + + def eip712_filtering_calldata_chain_id(self, + index: int, + sig: bytes, + discarded: bool): + data = bytearray() + data += struct.pack(">B", index) + data.append(len(sig)) + data += sig + return self._serialize(InsType.EIP712_SEND_FILTERING, + int(discarded), + P2Type.FILTERING_CALLDATA_CHAIN_ID, + data) + + def eip712_filtering_calldata_selector(self, + index: int, + sig: bytes, + discarded: bool): + data = bytearray() + data += struct.pack(">B", index) + data.append(len(sig)) + data += sig + return self._serialize(InsType.EIP712_SEND_FILTERING, + int(discarded), + P2Type.FILTERING_CALLDATA_SELECTOR, + data) + + def eip712_filtering_calldata_amount(self, + index: int, + sig: bytes, + discarded: bool): + data = bytearray() + data += struct.pack(">B", index) + data.append(len(sig)) + data += sig + return self._serialize(InsType.EIP712_SEND_FILTERING, + int(discarded), + P2Type.FILTERING_CALLDATA_AMOUNT, + data) + + def eip712_filtering_calldata_spender(self, + index: int, + sig: bytes, + discarded: bool): + data = bytearray() + data += struct.pack(">B", index) + data.append(len(sig)) + data += sig + return self._serialize(InsType.EIP712_SEND_FILTERING, + int(discarded), + P2Type.FILTERING_CALLDATA_SPENDER, + data) + def eip712_filtering_raw(self, name: str, sig: bytes, discarded: bool) -> bytes: return self._serialize(InsType.EIP712_SEND_FILTERING, int(discarded), @@ -279,15 +389,21 @@ def set_external_plugin(self, plugin_name: str, contract_address: bytes, selecto 0x00, data) - def sign(self, bip32_path: str, rlp_data: bytes, p2: int) -> list[bytes]: - apdus = [] - payload = pack_derivation_path(bip32_path) - payload += rlp_data + def sign(self, + mode: int, + bip32_path: Optional[str] = None, + rlp_data: Optional[bytes] = None) -> list[bytes]: + apdus: list[bytes] = [] + payload = bytearray() + if bip32_path is not None: + payload = pack_derivation_path(bip32_path) + if rlp_data is not None: + payload += rlp_data p1 = P1Type.SIGN_FIRST_CHUNK - while len(payload) > 0: + while (len(payload) > 0) or ((len(apdus) == 0) and (len(payload) == 0)): apdus.append(self._serialize(InsType.SIGN, p1, - p2, + mode, payload[:0xff])) payload = payload[0xff:] p1 = P1Type.SIGN_SUBSQT_CHUNK @@ -475,6 +591,9 @@ def provide_enum_value(self, tlv_payload: bytes) -> list[bytes]: def provide_transaction_info(self, tlv_payload: bytes) -> list[bytes]: return self.common_tlv_serialize(InsType.PROVIDE_TRANSACTION_INFO, tlv_payload) + def provide_transaction_field_desc(self, tlv_payload: bytes) -> list[bytes]: + return self.common_tlv_serialize(InsType.PROVIDE_TRANSACTION_FIELD_DESC, tlv_payload) + def opt_in_tx_simulation(self) -> bytes: # Serialize the payload return self._serialize(InsType.PROVIDE_TX_SIMULATION, P1Type.OPT_IN_TX_CHECK, 0x00) @@ -484,3 +603,6 @@ def provide_tx_simulation(self, tlv_payload: bytes) -> list[bytes]: def provide_proxy_info(self, tlv_payload: bytes) -> list[bytes]: return self.common_tlv_serialize(InsType.PROVIDE_PROXY_INFO, tlv_payload) + + def provide_safe_account(self, tlv_payload: bytes, p2: int) -> list[bytes]: + return self.common_tlv_serialize(InsType.PROVIDE_SAFE_ACCOUNT, tlv_payload, p2l=[p2]) diff --git a/client/src/ledger_app_clients/ethereum/eip712/InputData.py b/client/src/ledger_app_clients/ethereum/eip712/InputData.py index 6be247f8b..fef1364a3 100644 --- a/client/src/ledger_app_clients/ethereum/eip712/InputData.py +++ b/client/src/ledger_app_clients/ethereum/eip712/InputData.py @@ -1,33 +1,26 @@ import hashlib import json import re -import signal -import sys import copy -from typing import Any, Callable, Optional, Union +from typing import Any, Optional, Union, Callable import struct +import functools from client import keychain from client.client import EthAppClient, EIP712FieldType from client.ledger_pki import PKIPubKeyUsage +from client.status_word import StatusWord # global variables app_client: EthAppClient = None filtering_paths: dict = {} filtering_tokens: list[dict] = [] +filtering_calldatas: list[dict] = [] current_path: list[str] = [] sig_ctx: dict[str, Any] = {} -def default_handler(): - raise RuntimeError("Uninitialized handler") - - -autonext_handler: Callable = default_handler -is_golden_run: bool - - # From a string typename, extract the type and all the array depth # Input = "uint8[2][][4]" | "bool" # Output = ('uint8', [2, None, 4]) | ('bool', []) @@ -119,6 +112,11 @@ def send_struct_def_field(typename, keyname): array_lvls, keyname): pass + + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending field def {keyname} of type {typename}: {response.status}" + return (typename, type_enum, typesize, array_lvls) @@ -198,14 +196,17 @@ def send_filtering_token(token_idx: int): if len(filtering_tokens[token_idx]) > 0: token = filtering_tokens[token_idx] if not token["sent"]: - app_client.provide_token_metadata(token["ticker"], - bytes.fromhex(token["addr"][2:]), - token["decimals"], - token["chain_id"]) + response = app_client.provide_token_metadata(token["ticker"], + bytes.fromhex(token["addr"][2:]), + token["decimals"], + token["chain_id"]) + assert response.status == StatusWord.OK, \ + f"Error sending token metadata for {token['ticker']}: {response.status}" token["sent"] = True -def send_filter(path: str, discarded: bool): +def send_filter(path: str, discarded: bool) -> Optional[Callable]: + ret: Optional[Callable] = None assert path in filtering_paths.keys() if filtering_paths[path]["type"].startswith("amount_join_"): @@ -231,26 +232,67 @@ def send_filter(path: str, discarded: bool): filtering_paths[path]["tn_type"], filtering_paths[path]["tn_source"], discarded) + elif filtering_paths[path]["type"].startswith("calldata_"): + calldata_index = filtering_paths[path]["index"] + for calldata in filtering_calldatas: + if calldata["index"] == calldata_index: + if not calldata["sent"]: + send_filtering_calldata_info(calldata["index"], + calldata["value_flag"], + calldata["callee_flag"], + calldata["chain_id_flag"], + calldata["selector_flag"], + calldata["amount_flag"], + calldata["spender_flag"]) + calldata["sent"] = True + break + if filtering_paths[path]["type"].endswith("_value"): + send_filtering_calldata_value(path, calldata_index, discarded) + elif filtering_paths[path]["type"].endswith("_callee"): + send_filtering_calldata_callee(path, calldata_index, discarded) + elif filtering_paths[path]["type"].endswith("_chain_id"): + send_filtering_calldata_chain_id(path, calldata_index, discarded) + elif filtering_paths[path]["type"].endswith("_selector"): + send_filtering_calldata_selector(path, calldata_index, discarded) + elif filtering_paths[path]["type"].endswith("_amount"): + send_filtering_calldata_amount(path, calldata_index, discarded) + elif filtering_paths[path]["type"].endswith("_spender"): + send_filtering_calldata_spender(path, calldata_index, discarded) + else: + assert False + calldata["path_count"] -= 1 + if calldata["path_count"] == 0: + ret = calldata["handler"] elif filtering_paths[path]["type"] == "raw": send_filtering_raw(path, filtering_paths[path]["name"], discarded) else: assert False + return ret + def send_struct_impl_field(value, field): assert not isinstance(value, list) assert field["enum"] != EIP712FieldType.CUSTOM + callback: Optional[Callable] = None + data = encoding_functions[field["enum"]](value, field["typesize"]) if filtering_paths: path = ".".join(current_path) if path in filtering_paths.keys(): - send_filter(path, False) + callback = send_filter(path, False) with app_client.eip712_send_struct_impl_struct_field(data): - enable_autonext() - disable_autonext() + pass + + if callback is not None: + callback() + + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending field {field['name']} of type {field['type']}: {response.status}" def evaluate_field(structs, data, field, lvls_left, new_level=True): @@ -261,44 +303,42 @@ def evaluate_field(structs, data, field, lvls_left, new_level=True): if len(array_lvls) > 0 and lvls_left > 0: with app_client.eip712_send_struct_impl_array(len(data)): pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending array {field['name']} of type {field['type']}: {response.status}" if len(data) == 0: for path in filtering_paths.keys(): dpath = ".".join(current_path) + ".[]" if path.startswith(dpath): - app_client.eip712_filtering_discarded_path(path) + response = app_client.eip712_filtering_discarded_path(path) + assert response.status == StatusWord.OK, \ + f"Error sending discarded path {path}: {response.status}" send_filter(path, True) idx = 0 for subdata in data: current_path.append("[]") - if not evaluate_field(structs, subdata, field, lvls_left - 1, False): - return False + evaluate_field(structs, subdata, field, lvls_left - 1, False) current_path.pop() idx += 1 if array_lvls[lvls_left - 1] is not None: - if array_lvls[lvls_left - 1] != idx: - print(f"Mismatch in array size! Got {idx}, expected {array_lvls[lvls_left - 1]}\n", - file=sys.stderr) - return False + assert array_lvls[lvls_left - 1] == idx, \ + f"Mismatch in array size! Got {idx}, expected {array_lvls[lvls_left - 1]}" else: if field["enum"] == EIP712FieldType.CUSTOM: - if not send_struct_impl(structs, data, field["type"]): - return False + send_struct_impl(structs, data, field["type"]) else: send_struct_impl_field(data, field) if new_level: current_path.pop() - return True def send_struct_impl(structs, data, structname): # Check if it is a struct we don't known - if structname not in structs.keys(): - return False + assert structname in structs.keys(), \ + f"Unknown struct {structname} in types definition" for f in structs[structname]: - if not evaluate_field(structs, data[f["name"]], f, len(f["array_lvls"])): - return False - return True + evaluate_field(structs, data[f["name"]], f, len(f["array_lvls"])) def start_signature_payload(ctx: dict, magic: int) -> bytearray: @@ -320,8 +360,10 @@ def send_filtering_message_info(display_name: str, filters_count: int): sig = keychain.sign_data(keychain.Key.CAL, to_sign) with app_client.eip712_filtering_message_info(display_name, filters_count, sig): - enable_autonext() - disable_autonext() + pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending filtering message info for {display_name}: {response.status}" def send_filtering_amount_join_token(path: str, token_idx: int, discarded: bool): @@ -331,6 +373,9 @@ def send_filtering_amount_join_token(path: str, token_idx: int, discarded: bool) sig = keychain.sign_data(keychain.Key.CAL, to_sign) with app_client.eip712_filtering_amount_join_token(token_idx, sig, discarded): pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending filtering amount join token for {path} with token index {token_idx}: {response.status}" def send_filtering_amount_join_value(path: str, token_idx: int, display_name: str, discarded: bool): @@ -341,6 +386,9 @@ def send_filtering_amount_join_value(path: str, token_idx: int, display_name: st sig = keychain.sign_data(keychain.Key.CAL, to_sign) with app_client.eip712_filtering_amount_join_value(token_idx, display_name, sig, discarded): pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending filtering amount join value for {path} with token index {token_idx}: {response.status}" def send_filtering_datetime(path: str, display_name: str, discarded: bool): @@ -350,6 +398,9 @@ def send_filtering_datetime(path: str, display_name: str, discarded: bool): sig = keychain.sign_data(keychain.Key.CAL, to_sign) with app_client.eip712_filtering_datetime(display_name, sig, discarded): pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending filtering datetime for {path}: {response.status}" def send_filtering_trusted_name(path: str, @@ -367,6 +418,97 @@ def send_filtering_trusted_name(path: str, sig = keychain.sign_data(keychain.Key.CAL, to_sign) with app_client.eip712_filtering_trusted_name(display_name, name_type, name_source, sig, discarded): pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending filtering trusted name for {path}: {response.status}" + + +def send_filtering_calldata_info(index: int, + value_filter_flag: bool, + callee_filter_flag: int, + chain_id_filter_flag: bool, + selector_filter_flag: bool, + amount_filter_flag: bool, + spender_filter_flag: int): + to_sign = start_signature_payload(sig_ctx, 55) + to_sign.append(index) + to_sign.append(value_filter_flag) + to_sign.append(int(callee_filter_flag)) + to_sign.append(chain_id_filter_flag) + to_sign.append(selector_filter_flag) + to_sign.append(amount_filter_flag) + to_sign.append(int(spender_filter_flag)) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + response = app_client.eip712_filtering_calldata_info(index, + value_filter_flag, + callee_filter_flag, + chain_id_filter_flag, + selector_filter_flag, + amount_filter_flag, + spender_filter_flag, + sig) + assert response.status == StatusWord.OK, \ + f"Error sending filtering calldata info : {response.status}" + + +def send_filtering_calldata_value(path: str, index: int, discarded: bool): + to_sign = start_signature_payload(sig_ctx, 66) + to_sign += path.encode() + to_sign.append(index) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + response = app_client.eip712_filtering_calldata_value(index, sig, discarded) + assert response.status == StatusWord.OK, \ + f"Error sending filtering calldata value for {path}: {response.status}" + + +def send_filtering_calldata_callee(path: str, index: int, discarded: bool): + to_sign = start_signature_payload(sig_ctx, 77) + to_sign += path.encode() + to_sign.append(index) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + response = app_client.eip712_filtering_calldata_callee(index, sig, discarded) + assert response.status == StatusWord.OK, \ + f"Error sending filtering calldata callee for {path}: {response.status}" + + +def send_filtering_calldata_chain_id(path: str, index: int, discarded: bool): + to_sign = start_signature_payload(sig_ctx, 88) + to_sign += path.encode() + to_sign.append(index) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + response = app_client.eip712_filtering_calldata_chain_id(index, sig, discarded) + assert response.status == StatusWord.OK, \ + f"Error sending filtering calldata callee for {path}: {response.status}" + + +def send_filtering_calldata_selector(path: str, index: int, discarded: bool): + to_sign = start_signature_payload(sig_ctx, 99) + to_sign += path.encode() + to_sign.append(index) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + response = app_client.eip712_filtering_calldata_selector(index, sig, discarded) + assert response.status == StatusWord.OK, \ + f"Error sending filtering calldata callee for {path}: {response.status}" + + +def send_filtering_calldata_amount(path: str, index: int, discarded: bool): + to_sign = start_signature_payload(sig_ctx, 110) + to_sign += path.encode() + to_sign.append(index) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + response = app_client.eip712_filtering_calldata_amount(index, sig, discarded) + assert response.status == StatusWord.OK, \ + f"Error sending filtering calldata callee for {path}: {response.status}" + + +def send_filtering_calldata_spender(path: str, index: int, discarded: bool): + to_sign = start_signature_payload(sig_ctx, 121) + to_sign += path.encode() + to_sign.append(index) + sig = keychain.sign_data(keychain.Key.CAL, to_sign) + response = app_client.eip712_filtering_calldata_spender(index, sig, discarded) + assert response.status == StatusWord.OK, \ + f"Error sending filtering calldata callee for {path}: {response.status}" # ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures @@ -377,11 +519,15 @@ def send_filtering_raw(path: str, display_name: str, discarded: bool): sig = keychain.sign_data(keychain.Key.CAL, to_sign) with app_client.eip712_filtering_raw(display_name, sig, discarded): pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending filtering raw for {path}: {response.status}" -def prepare_filtering(filtr_data): +def prepare_filtering(data_json, filtr_data): global filtering_paths global filtering_tokens + global filtering_calldatas if "fields" in filtr_data: filtering_paths = filtr_data["fields"] @@ -396,6 +542,21 @@ def prepare_filtering(filtr_data): else: filtering_tokens = [] + if "calldatas" in filtr_data: + filtering_calldatas = filtr_data["calldatas"] + for calldata in filtering_calldatas: + calldata["sent"] = False + calldata["path_count"] = 0 + for path in filtering_paths.values(): + if path["type"].startswith("calldata_"): + if path["index"] == calldata["index"]: + calldata["path_count"] += 1 + if "handler" in calldata: + if calldata["handler"] is not None: + calldata["handler"] = functools.partial(calldata["handler"], app_client, data_json) + else: + calldata["handler"] = None + def handle_optional_domain_values(domain): if "chainId" not in domain.keys(): @@ -418,38 +579,21 @@ def init_signature_context(types, domain, filters): for i in range(8): sig_ctx["chainid"].append(chainid & (0xff << (i * 8))) sig_ctx["chainid"].reverse() + + # Order type fields + for type_name in types.keys(): + for i in range(len(types[type_name])): + types[type_name][i] = dict(sorted(types[type_name][i].items())) + schema_str = json.dumps(types).replace(" ", "") schema_hash = hashlib.sha224(schema_str.encode()) sig_ctx["schema_hash"] = bytearray.fromhex(schema_hash.hexdigest()) -def next_timeout(_signum: int, _frame): - autonext_handler() - - -def enable_autonext(): - delay = 1/4 if app_client.device.is_nano else 1/2 - - # golden run has to be slower to make sure we take good snapshots - # and not processing/loading screens - if is_golden_run: - delay *= 3 - - signal.setitimer(signal.ITIMER_REAL, delay, delay) - - -def disable_autonext(): - signal.setitimer(signal.ITIMER_REAL, 0, 0) - - def process_data(aclient: EthAppClient, data_json: dict, - filters: Optional[dict] = None, - autonext: Optional[Callable] = None, - golden_run: bool = False) -> bool: + filters: Optional[dict] = None) -> None: global app_client - global autonext_handler - global is_golden_run global current_path current_path = [] @@ -462,12 +606,6 @@ def process_data(aclient: EthAppClient, domain = data_json["domain"] message = data_json["message"] - if autonext: - autonext_handler = autonext - signal.signal(signal.SIGALRM, next_timeout) - - is_golden_run = golden_run - if filters: init_signature_context(types, domain, filters) @@ -475,6 +613,9 @@ def process_data(aclient: EthAppClient, for key in types.keys(): with app_client.eip712_send_struct_def_struct_name(key): pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending struct def {key}: {response.status}" for f in types[key]: (f["type"], f["enum"], f["typesize"], f["array_lvls"]) = \ send_struct_def_field(f["type"], f["name"]) @@ -482,17 +623,21 @@ def process_data(aclient: EthAppClient, if filters: with app_client.eip712_filtering_activate(): pass - prepare_filtering(filters) + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error activating filtering: {response.status}" + prepare_filtering(data_json, filters) # Send ledgerPKI certificate app_client.pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_COIN_META) # send domain implementation with app_client.eip712_send_struct_impl_root_struct(domain_typename): - enable_autonext() - disable_autonext() - if not send_struct_impl(types, domain, domain_typename): - return False + pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending domain root struct {domain_typename}: {response.status}" + send_struct_impl(types, domain, domain_typename) if filters: if filters and "name" in filters: @@ -502,9 +647,8 @@ def process_data(aclient: EthAppClient, # send message implementation with app_client.eip712_send_struct_impl_root_struct(message_typename): - enable_autonext() - disable_autonext() - if not send_struct_impl(types, message, message_typename): - return False - - return True + pass + response = app_client.response() + assert response.status == StatusWord.OK, \ + f"Error sending message root struct {message_typename}: {response.status}" + send_struct_impl(types, message, message_typename) diff --git a/client/src/ledger_app_clients/ethereum/gcs.py b/client/src/ledger_app_clients/ethereum/gcs.py index 0890ec9af..092b04f17 100644 --- a/client/src/ledger_app_clients/ethereum/gcs.py +++ b/client/src/ledger_app_clients/ethereum/gcs.py @@ -243,11 +243,16 @@ def serialize(self) -> bytes: return payload -class ParamRaw(TlvSerializable): +class FieldParam(TlvSerializable): + type: ParamType + + +class ParamRaw(FieldParam): version: int value: Value def __init__(self, version: int, value: Value): + self.type = ParamType.RAW self.version = version self.value = value @@ -258,11 +263,12 @@ def serialize(self) -> bytes: return payload -class ParamAmount(TlvSerializable): +class ParamAmount(FieldParam): version: int value: Value def __init__(self, version: int, value: Value): + self.type = ParamType.AMOUNT self.version = version self.value = value @@ -273,7 +279,7 @@ def serialize(self) -> bytes: return payload -class ParamTokenAmount(TlvSerializable): +class ParamTokenAmount(FieldParam): version: int value: Value token: Optional[Value] @@ -288,6 +294,7 @@ def __init__(self, native_currency: Optional[list[bytes]] = None, threshold: Optional[int] = None, above_threshold_msg: Optional[str] = None): + self.type = ParamType.TOKEN_AMOUNT self.version = version self.value = value self.token = token @@ -311,12 +318,13 @@ def serialize(self) -> bytes: return payload -class ParamNFT(TlvSerializable): +class ParamNFT(FieldParam): version: int id: Value collection: Value def __init__(self, version: int, id: Value, collection: Value): + self.type = ParamType.NFT self.version = version self.id = id self.collection = collection @@ -334,29 +342,31 @@ class DatetimeType(IntEnum): DT_BLOCKHEIGHT = 0x01 -class ParamDatetime(TlvSerializable): +class ParamDatetime(FieldParam): version: int value: Value - type: DatetimeType + dt_type: DatetimeType def __init__(self, version: int, value: Value, type: DatetimeType): + self.type = ParamType.DATETIME self.version = version self.value = value - self.type = type + self.dt_type = type def serialize(self) -> bytes: payload = bytearray() payload += self.serialize_field(0x00, self.version) payload += self.serialize_field(0x01, self.value.serialize()) - payload += self.serialize_field(0x02, self.type) + payload += self.serialize_field(0x02, self.dt_type) return payload -class ParamDuration(TlvSerializable): +class ParamDuration(FieldParam): version: int value: Value def __init__(self, version: int, value: Value): + self.type = ParamType.DURATION self.version = version self.value = value @@ -367,7 +377,7 @@ def serialize(self) -> bytes: return payload -class ParamUnit(TlvSerializable): +class ParamUnit(FieldParam): version: int value: Value base: str @@ -380,6 +390,7 @@ def __init__(self, base: str, decimals: Optional[int] = None, prefix: Optional[bool] = None): + self.type = ParamType.UNIT self.version = version self.value = value self.base = base @@ -398,7 +409,7 @@ def serialize(self) -> bytes: return payload -class ParamTrustedName(TlvSerializable): +class ParamTrustedName(FieldParam): version: int value: Value types: list[TrustedNameType] @@ -411,6 +422,7 @@ def __init__(self, types: list[TrustedNameType], sources: list[TrustedNameSource], sender_addrs: Optional[list[bytes]] = None): + self.type = ParamType.TRUSTED_NAME self.version = version self.value = value self.types = types @@ -435,12 +447,13 @@ def serialize(self) -> bytes: return payload -class ParamEnum(TlvSerializable): +class ParamEnum(FieldParam): version: int id: int value: Value def __init__(self, version: int, id: int, value: Value): + self.type = ParamType.ENUM self.version = version self.id = id self.value = value @@ -453,12 +466,55 @@ def serialize(self) -> bytes: return payload -class ParamToken(TlvSerializable): +class ParamCalldata(FieldParam): + version: int + calldata: Value + contract_addr: Value + chain_id: Optional[Value] + selector: Optional[Value] + amount: Optional[Value] + spender: Optional[Value] + + def __init__(self, + version: int, + calldata: Value, + contract_addr: Value, + chain_id: Optional[Value] = None, + selector: Optional[Value] = None, + amount: Optional[Value] = None, + spender: Optional[Value] = None): + self.type = ParamType.CALLDATA + self.version = version + self.calldata = calldata + self.contract_addr = contract_addr + self.chain_id = chain_id + self.selector = selector + self.amount = amount + self.spender = spender + + def serialize(self) -> bytes: + payload = bytearray() + payload += self.serialize_field(0x00, self.version) + payload += self.serialize_field(0x01, self.calldata.serialize()) + payload += self.serialize_field(0x02, self.contract_addr.serialize()) + if self.chain_id is not None: + payload += self.serialize_field(0x03, self.chain_id.serialize()) + if self.selector is not None: + payload += self.serialize_field(0x04, self.selector.serialize()) + if self.amount is not None: + payload += self.serialize_field(0x05, self.amount.serialize()) + if self.spender is not None: + payload += self.serialize_field(0x06, self.spender.serialize()) + return payload + + +class ParamToken(FieldParam): version: int addr: Value native_currency: Optional[list[bytes]] def __init__(self, version, addr: Value, native_currency: Optional[list[bytes]] = None): + self.type = ParamType.TOKEN self.version = version self.addr = addr self.native_currency = native_currency @@ -476,19 +532,17 @@ def serialize(self) -> bytes: class Field(TlvSerializable): version: int name: str - param_type: ParamType - param: TlvSerializable + param: FieldParam - def __init__(self, version: int, name: str, param_type: ParamType, param: TlvSerializable): + def __init__(self, version: int, name: str, param: FieldParam): self.version = version self.name = name - self.param_type = param_type self.param = param def serialize(self) -> bytes: payload = bytearray() payload += self.serialize_field(0x00, self.version) payload += self.serialize_field(0x01, self.name) - payload += self.serialize_field(0x02, self.param_type) + payload += self.serialize_field(0x02, self.param.type) payload += self.serialize_field(0x03, self.param.serialize()) return payload diff --git a/client/src/ledger_app_clients/ethereum/keychain.py b/client/src/ledger_app_clients/ethereum/keychain.py index 6ec53ad53..8d9574c9c 100644 --- a/client/src/ledger_app_clients/ethereum/keychain.py +++ b/client/src/ledger_app_clients/ethereum/keychain.py @@ -15,6 +15,7 @@ class Key(Enum): CALLDATA = auto() NETWORK = auto() TRANSACTION_CHECKS = auto() + SAFE = auto() _keys: dict[Key, SigningKey] = {} diff --git a/client/src/ledger_app_clients/ethereum/keychain/safe.pem b/client/src/ledger_app_clients/ethereum/keychain/safe.pem new file mode 100644 index 000000000..a20062f2b --- /dev/null +++ b/client/src/ledger_app_clients/ethereum/keychain/safe.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQACg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHQCAQEEIFSzDKWxAx1gEJiLlPkeRWSrM3FIImRSo5UzC5T+w14ToAcGBSuBBAAK +oUQDQgAE6YAKO+5HIFz1A4mQSwNbTTPN+JS95zqDyIqYvELBQZxYNtLyF9iIjXqb +k1EVmLhEVDbXQ9BPIeaOS2/DLyjxOQ== +-----END EC PRIVATE KEY----- diff --git a/client/src/ledger_app_clients/ethereum/ledger_pki.py b/client/src/ledger_app_clients/ethereum/ledger_pki.py index 8d4f33eb7..9cd7261dc 100644 --- a/client/src/ledger_app_clients/ethereum/ledger_pki.py +++ b/client/src/ledger_app_clients/ethereum/ledger_pki.py @@ -2,7 +2,7 @@ from ledgered.devices import DeviceType -from ragger.backend import BackendInterface +from ragger.backend import BackendInterface, SpeculosBackend from ragger.utils import RAPDU from .status_word import StatusWord @@ -21,6 +21,7 @@ class PKIPubKeyUsage(IntEnum): PUBKEY_USAGE_TX_SIMU_SIGNER = 0x0a PUBKEY_USAGE_CALLDATA = 0x0b PUBKEY_USAGE_NETWORK = 0x0c + PUBKEY_USAGE_SAFE_ACCOUNT = 0x0e # pylint: disable=line-too-long @@ -30,72 +31,104 @@ class PKIPubKeyUsage(IntEnum): DeviceType.NANOX: "", # noqa: E501 DeviceType.STAX: "", # noqa: E501 DeviceType.FLEX: "", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_EXCHANGE_PAYLOAD: { DeviceType.NANOSP: "", # noqa: E501 DeviceType.NANOX: "", # noqa: E501 DeviceType.STAX: "", # noqa: E501 DeviceType.FLEX: "", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_NFT_METADATA: { DeviceType.NANOSP: "0101010201021004010200001104000000021201001302000214010116040000000020084e46545f496e666f300200043101033201213321023cfb5fb31905f4bd39d9d535a40c26aab51c5d7d3219b28ac942b980fb206cfb34010135010315473045022100d43e142a6639b27a79bc4f021854df48f1bc1e828ac47b105578cb527b69f525022078f6e6b3eb9bb787a0a29e85531ce3512c2d6481e761e840db0fb6b0898911a1", # noqa: E501 DeviceType.NANOX: "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB340101350102154730450221009BAE21BB8CBA6F95DDFF86AEEA991D63FA36A469A3071F61BDA8895F1A5F0AC3022061661F95D1513D3FDE81FFEA4B0C6D48ADCB27ED70915EE3ACD16A2A64CDE916", # noqa: E501 DeviceType.STAX: "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB3401013501041546304402201DEE04EC830FFDE5C98A708EC6865605FC14FF6105A54BE5230F2B954C673B940220581A0A5E42A7779140963703E43B3BEABE4C69284EDEF00E76BB5875E0810C9B", # noqa: E501 DeviceType.FLEX: "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB340101350105154730450221009ABCC7056D54C1B5DBB353178B13850C20521EE6884AA415AA61B329DB1D87F602204E308F273B8D18080184695438577F770524F717E5D08EE20ECBF1BC599F3538", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "0101010201021104000000021201001302000214010116040000000020084E46545F496E666F300200043101033201213321023CFB5FB31905F4BD39D9D535A40C26AAB51C5D7D3219B28AC942B980FB206CFB340101350106154630440220358C092F067DB8AA438BB87C50D5E4E5A3AB364A88BE3032712C712F807012F102205EB31FFC85214F37C36A24DB0518AB3D2F1B62B3169D382E788EB99842520165", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_TRUSTED_NAME: { DeviceType.NANOSP: "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F6534010135010315473045022100F394484C045418507E0F76A3231F233B920C733D3E5BB68AFBAA80A55195F70D022012BC1FD796CD2081D8355DEEFA051FBB9329E34826FF3125098F4C6A0C29992A", # noqa: E501 DeviceType.NANOX: "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F65340101350102154730450221009D97646C49EE771BE56C321AB59C732E10D5D363EBB9944BF284A3A04EC5A14102200633518E851984A7EA00C5F81EDA9DAA58B4A6C98E57DA1FBB9074AEFF0FE49F", # noqa: E501 DeviceType.STAX: "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F6534010135010415473045022100A57DC7AB3F0E38A8D10783C7449024D929C60843BB75E5FF7B8088CB71CB130C022045A03E6F501F3702871466473BA08CE1F111357ED9EF395959733477165924C4", # noqa: E501 DeviceType.FLEX: "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F6534010135010515473045022100D5BB77756C3D7C1B4254EA8D5351B94A89B13BA69C3631A523F293A10B7144B302201519B29A882BB22DCDDF6BE79A9CBA76566717FA877B7CA4B9CC40361A2D579E", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "01010102010211040000000212010013020002140101160400000000200C547275737465645F4E616D6530020007310104320121332102B91FBEC173E3BA4A714E014EBC827B6F899A9FA7F4AC769CDE284317A00F4F65340101350106154630440220200261047BAF050570EA5105D1E05855131CB98A94C58B019732F849BD1CE5330220237D303A9606EA631DDD3E5E12D2A70878A0ED954D975BF55DD7A84BF08506AA", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_BACKUP_PROVIDER: { DeviceType.NANOSP: "", # noqa: E501 DeviceType.NANOX: "", # noqa: E501 DeviceType.STAX: "", # noqa: E501 DeviceType.FLEX: "", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_RECOVER_ORCHESTRATOR: { DeviceType.NANOSP: "", # noqa: E501 DeviceType.NANOX: "", # noqa: E501 DeviceType.STAX: "", # noqa: E501 DeviceType.FLEX: "", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_PLUGIN_METADATA: { DeviceType.NANOSP: "01010102010210040102000011040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE3340101350103154630440220401824348DA0E435C9BF16C3591665CFA1B7D8E729971BE884027E02BD3C35A102202289EE207B73D98E9E6110CC143EB929F03B99D54C63023C99561D3CE164D30F", # noqa: E501 DeviceType.NANOX: "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010215473045022100E657DE255F954779E14D281E2E739D89DEF2E943B7FD4B4AFE49CF4FF7E1D84F022057F29C9AEA8FAA25C8438FDEE85C6DABF270E5CEC1655F17F2D9A6ADCD3ADC0E", # noqa: E501 DeviceType.STAX: "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010415473045022100B8AF9667C190B60BF350D8F8CA66A4BCEA22BF47D757CB7F88F8D16C7794BCDC02205F7D6C8E9294F73744A82E1062B10FFEB809252682112E71A419EFC78227211B", # noqa: E501 DeviceType.FLEX: "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010515473045022100F5069D8BCEDCF7CC55273266E3871B09FFCACD084B5753347A809DDDA67E6235022003CE65364BFA96B6FE7A9D8C13EC87B8E727E8B7BF4A63176F5D61AB8F97807E", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "01010102010211040000000212010013020002140101160400000000200A53657420506C7567696E30020003310107320121332103C055BC4ECF055E2D85085D35127A3DE6705C7F885055CD7071E87671BF191FE334010135010615473045022100C245D6D6A39022C2DD73F3DFFAE2BEACCE442AE082D26900A9E1AE01DAEF525402203C558BB2AC20C37FD5847424ACF73C301B0DC188D63A1183786259B7919ACDE9", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_COIN_META: { DeviceType.NANOSP: "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010310040102000015473045022100C15795C2AE41E6FAE6B1362EE1AE216428507D7C1D6939B928559CC7A1F6425C02206139CF2E133DD62F3E00F183E42109C9853AC62B6B70C5079B9A80DBB9D54AB5", # noqa: E501 DeviceType.NANOX: "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100E3B956F93FBFF0D41908483888F0F75D4714662A692F7A38DC6C41A13294F9370220471991BECB3CA4F43413CADC8FF738A8CC03568BFA832B4DCFE8C469080984E5", # noqa: E501 DeviceType.STAX: "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501041546304402206731FCD3E2432C5CA162381392FD17AD3A41EEF852E1D706F21A656AB165263602204B89FAE8DBAF191E2D79FB00EBA80D613CB7EDF0BE960CB6F6B29D96E1437F5F", # noqa: E501 DeviceType.FLEX: "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010515473045022100B59EA8B958AA40578A6FBE9BBFB761020ACD5DBD8AA863C11DA17F42B2AFDE790220186316059EFA58811337D47C7F815F772EA42BBBCEA4AE123D1118C80588F5CB", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501061546304402207AB71BB46DD2361292195E95587D14FEDE2BA10FC23F0D6B20444B93A32258D302201362A6815779B2806005B0151BFADB811B78A76FDB90028FBE6C93EB7FB5EEA3", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_SEED_ID_AUTH: { DeviceType.NANOSP: "", # noqa: E501 DeviceType.NANOX: "", # noqa: E501 DeviceType.STAX: "", # noqa: E501 DeviceType.FLEX: "", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_TX_SIMU_SIGNER: { DeviceType.NANOSP: "01010102010211040000000212010013020002140101160400000000200A573343204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF550134010135010315473045022100EABC9E26361DD551E30F52604884E5D0DAEF9EDD63848C45DA0B446DEE870BF002206AC308F46D04E5B23CC8D62F9C062E3AF931E3EEF9C2509AFA768A891CA8F10B", # noqa: E501 DeviceType.NANOX: "01010102010211040000000212010013020002140101160400000000200A573343204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF550134010135010215473045022100B9EC810718F85C110CF60E7C5A8A6A4F783F3E0918E93861A8FCDCE7CFF4D405022047BD29E3F2B8EFD3FC7451FA19EE3147C38BEF83246DC396E7A10B2D2A44DB30", # noqa: E501 DeviceType.STAX: "01010102010211040000000212010013020002140101160400000000200A573343204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF550134010135010415473045022100C490C9DD99F7D1A39D3AE9D448762DEAA17694C9BCF00454503498D2BA883DFE02204AEAD903C2B3A106206D7C2B1ACAA6DD20B6B41EE6AEF38F060F05EC4D7813BB", # noqa: E501 DeviceType.FLEX: "01010102010211040000000212010013020002140101160400000000200A573343204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF550134010135010515473045022100FFDE724191BAA18250C7A93404D57CE13465797979EAF64239DB221BA679C5A402206E02953F47D32299F82616713D3DBA39CF8A09EF948B23446A6DDE610F80D066", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "01010102010211040000000212010013020002140101160400000000200E54782053696D75204C65646765723002000531010A320121332103DA154C97512390BDFDD0E2178523EF7B2486B7A7DD5B507079D2F3641AEF5501340101350106154630440220191804783BC24CD8D4668558A82E19730C2EC7BEFFF90AD191845C8D524358D802201D491FCE10F2CEBD03839A89794C86DCF8F7A0C83364213D140937B3EF1DE9C5", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_CALLDATA: { DeviceType.NANOSP: "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010315463044022076DD2EAB72E69D440D6ED8290C8C37E39F54294C23FF0F8520F836E7BE07455C02201D9A8A75223C1ADA1D9D00966A12EBB919D0BBF2E66F144C83FADCAA23672566", # noqa: E501 DeviceType.NANOX: "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010215463044022077FF9625006CB8A4AD41A4B04FF2112E92A732BD263CCE9B97D8E7D2536D04300220445B8EE3616FB907AA5E68359275E94D0A099C3E32A4FC8B3669C34083671F2F", # noqa: E501 DeviceType.STAX: "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B434010135010415473045022100A88646AD72CA012D5FDAF8F6AE0B7EBEF079212768D57323CB5B57CADD9EB20D022005872F8EA06092C9783F01AF02C5510588FB60CBF4BA51FB382B39C1E060BB6B", # noqa: E501 DeviceType.FLEX: "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B43401013501051546304402205305BDDDAD0284A2EAC2A9BE4CEF6604AE9415C5F46883448F5F6325026234A3022001ED743BCF33CCEB070FDD73C3D3FCC2CEE5AB30A5C3EB7D2A8D21C6F58D493F", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "01010102010211040000000212010013020002140101160400000000200863616C6C646174613002000831010B32012133210381C0821E2A14AC2546FB0B9852F37CA2789D7D76483D79217FB36F51DCE1E7B4340101350106154730450221009F5EDA5B6ED34FA9F1C44B1CC234BE5FE6C0DD4655F42EE50CA6201F59491E5A02206E055F490F56F42B625F2B5772AE860CAC6848B6C5AC8E44BC529A959249FC37", # noqa: E501 }, PKIPubKeyUsage.PUBKEY_USAGE_NETWORK: { DeviceType.NANOSP: "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C3401013501031546304402207BDE0D30C0A573ECF2F8377F30D9A064CFDD8C85E3B328E4C0867A5C7E95EC7E02204B3546342571AE54E7524DD66D4F801E3E4F4F2EA9008F943661F62E48053E92", # noqa: E501 DeviceType.NANOX: "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010215473045022100E1CE7DAC7A23B9422B0764F8FE80246B2CF0780227289FBFB203985DA6326A9502205F90B43600407A094DD6DEBCEB92F34DA3EDA9EB5463568440BDC21635FF2044", # noqa: E501 DeviceType.STAX: "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010415463044022044C595C3E98100D4ECA75A73BF294090FF94948E80EE1430624C886B15BE862302200994E1D98CA72B78D57808B5FD236F439376AFC7C651B55D4AFBFB5AF4C15E00", # noqa: E501 DeviceType.FLEX: "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010515463044022008D276684F1A1CC3A89DB0B15120860414FF6A60E227FCAA29ED8F2096C982460220343FE956D443CEA33A2F8BD9DD1EAD783ACFF86088CF01BCE63C224DC815D7F0", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "0101010201021104000000021201001302000214010116040000000020076E6574776F726B3002000A31010C32012133210304AF5CF32094F855E93235E9EB43F48E9B436C2E1DFAEA58ECAFA68AAFB1D27C34010135010615473045022100D41A10CCDC754B40F936AE324124FA23A6C44F6F2F8900D675D784A884CFAC2302203247F487D46BAAFE20710104BEF86288697863DD66747E6FB44EC336FA6F6CB8", # noqa: E501 + }, + PKIPubKeyUsage.PUBKEY_USAGE_SAFE_ACCOUNT: { + DeviceType.NANOSP: "010101020102110400000002120100130200021401011604000000002004536166653002000531010E320121332103E9800A3BEE47205CF50389904B035B4D33CDF894BDE73A83C88A98BC42C1419C3401013501031546304402204A264024F1EDE245F251C0D5C41DE7CAD7C3F2DAF1418181A706DE7EE3BD9B4F02206461E5F6F319D3C5F7451332A9C35CE0D7B26C47B8400A178F486A61C9DFE0AE", # noqa: E501 + DeviceType.NANOX: "010101020102110400000002120100130200021401011604000000002004536166653002000531010E320121332103E9800A3BEE47205CF50389904B035B4D33CDF894BDE73A83C88A98BC42C1419C34010135010215473045022100D17CA5CA9A14A6E89D1514C5AEF6F13A28384366DD2533B12A891B48DB81C3C8022049E0C97090294F780A02F75576EA18CE83D22EC55C0328A52D5B74D7B717F82B", # noqa: E501 + DeviceType.STAX: "010101020102110400000002120100130200021401011604000000002004536166653002000531010E320121332103E9800A3BEE47205CF50389904B035B4D33CDF894BDE73A83C88A98BC42C1419C34010135010415463044022040A2E9E1C022CF952BDC25FF9B9CD0AD184872E5FE3A73BE1DA942EF7F4849A6022071A00FCC4629762A0EFF51C959A73D2A8F071AAAC40F98AD68ADD34075577FCC", # noqa: E501 + DeviceType.FLEX: "010101020102110400000002120100130200021401011604000000002004536166653002000531010E320121332103E9800A3BEE47205CF50389904B035B4D33CDF894BDE73A83C88A98BC42C1419C3401013501051546304402204590D06CA60D7EA777550DF4D2D4ACEDFD70596445E053EC2E2AED7EBBDFA1C4022038FF8ED142A044138FF8CC7F684B0334721D9E12D0B65C41F32F8153F1EF8D55", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "010101020102110400000002120100130200021401011604000000002004536166653002000531010E320121332103E9800A3BEE47205CF50389904B035B4D33CDF894BDE73A83C88A98BC42C1419C34010135010615473045022100EEDA7D85FF4B3B162060C580B5F039898C6FBBDD894DBA1625764CFE4A5175ED02200F33F00DC0379BDBA9832062B6FDB926FB3F8B4ABEC3BC7ADA92BD2F80DAF295", # noqa: E501 }, } @@ -106,6 +139,8 @@ class PKIPubKeyUsage(IntEnum): DeviceType.NANOX: "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100BCAED6896A3413657F7F936F53FFF5BD7E30498B1109EAB878135F6DD4AAE555022056913EF42F166BEFEEDDB06C1F7AEEDE8712828F37B916E3E6DA7AE0809558E4", # noqa: E501 DeviceType.STAX: "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010415473045022100ABA9D58446EE81EB073DA91941989DD7E133556D58DE2BCBA59E46253DB448B102201DF8AE930A9E318B50576D8922503A5D3EC84C00C332A7C8FF7CD48708751840", # noqa: E501 DeviceType.FLEX: "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501051546304402206DC9F82C53F3B13400D3E343E3C8C81868E8C73B1EF2655D07891064B7AC3166022069A36E4059D75C93E488A5D58C02BCA9C80C081F77B31C5EDCF07F1A500C565A", # noqa: E501 + DeviceType.APEX_M: "", # noqa: E501 + DeviceType.APEX_P: "010101020102110400000002120100130200021401011604000000002010547275737465645F4E616D655F43414C300200093101043201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010615473045022100BF6920A641076921E6DCE96D77BC70581A28B73E932F8D2E117BFE8F48E9FC5F0220088FA292BB19B5F7594145F65614FDA65B899598FCA7A306E08926F67359EAA5", # noqa: E501 }, } # pylint: enable=line-too-long @@ -123,6 +158,9 @@ def __init__(self, backend: BackendInterface) -> None: self._backend = backend def send_certificate(self, key_usage: PKIPubKeyUsage, from_CAL: bool = False) -> None: + if not isinstance(self._backend, SpeculosBackend): + print("Warning: Only Speculos supports test PKI certificates.") + return certificates = PKI_CERTIFICATES_CAL if from_CAL else PKI_CERTIFICATES if key_usage not in certificates: raise ValueError(f"Unsupported key usage {key_usage}") diff --git a/client/src/ledger_app_clients/ethereum/safe.py b/client/src/ledger_app_clients/ethereum/safe.py new file mode 100644 index 000000000..af765c01b --- /dev/null +++ b/client/src/ledger_app_clients/ethereum/safe.py @@ -0,0 +1,73 @@ +from enum import IntEnum +from typing import List, Optional +from .tlv import TlvSerializable, FieldTag +from .keychain import sign_data, Key + + +class AccountType(IntEnum): + SAFE = 0x00 + SIGNER = 0x01 + + +class LesMultiSigRole(IntEnum): + SIGNER = 0x00 + PROPOSER = 0x01 + + +class SafeAccount(TlvSerializable): + account_type: AccountType + challenge: int = 0 + address: List[bytes] = [] + lesm_role: Optional[LesMultiSigRole] = None + threshold: int = 0 + signer_counts: int = 0 + signature: Optional[bytes] + + def __init__(self, + account_type: AccountType, + challenge: int, + address: List[bytes], + lesm_role: Optional[LesMultiSigRole] = None, + threshold: int = 0, + signer_counts: int = 0, + signature: Optional[bytes] = None) -> None: + assert account_type in (AccountType.SAFE, AccountType.SIGNER), \ + f"Invalid account_type: {account_type}. Must be SAFE(0) or SIGNER(1)" + if account_type == AccountType.SAFE: + assert len(address) == 1, "Only a single Address for SAFE accounts is allowed" + assert lesm_role in (LesMultiSigRole.SIGNER, LesMultiSigRole.PROPOSER), \ + f"Invalid lesm_role: {lesm_role}. Must be SIGNER(0) or PROPOSER(1)" + self.account_type = account_type + self.challenge = challenge + self.address = address + if account_type == AccountType.SAFE: + self.lesm_role = lesm_role + self.threshold = threshold + self.signer_counts = signer_counts + self.signature = signature + + def serialize(self) -> bytes: + assert self.address is not None, "Address is required" + assert self.challenge is not None, "Challenge is required" + if self.account_type == AccountType.SAFE: + assert self.threshold > 0, "Threshold must be greater than 0" + assert self.signer_counts > 0, "Signer counts must be greater than 0" + assert self.lesm_role is not None, "LESM role is required for SAFE accounts" + # Construct the TLV payload + payload: bytes = self.serialize_field(FieldTag.STRUCT_TYPE, 0x27) + payload += self.serialize_field(FieldTag.STRUCT_VERSION, 1) + payload += self.serialize_field(FieldTag.CHALLENGE, self.challenge) + for addr in self.address: + payload += self.serialize_field(FieldTag.ADDRESS, addr) + if self.account_type == AccountType.SAFE: + if self.lesm_role is not None: + payload += self.serialize_field(FieldTag.LESM_ROLE, self.lesm_role) + payload += self.serialize_field(FieldTag.THRESHOLD, self.threshold) + payload += self.serialize_field(FieldTag.SIGNERS_COUNT, self.signer_counts) + + # Append the data Signature + sig = self.signature + if sig is None: + sig = sign_data(Key.SAFE, payload) + payload += self.serialize_field(FieldTag.DER_SIGNATURE, sig) + return payload diff --git a/client/src/ledger_app_clients/ethereum/settings.py b/client/src/ledger_app_clients/ethereum/settings.py index 4ea70014b..7d7b15935 100644 --- a/client/src/ledger_app_clients/ethereum/settings.py +++ b/client/src/ledger_app_clients/ethereum/settings.py @@ -35,6 +35,24 @@ class SettingID(Enum): SettingID.EIP7702: (2, 420, 270), SettingID.DISPLAY_HASH: (3, 420, 130), }, + DeviceType.APEX_P: { + SettingID.TRANSACTION_CHECKS: (0, 260, 90), + SettingID.BLIND_SIGNING: (0, 260, 235), + SettingID.NONCE: (1, 260, 90), + SettingID.VERBOSE_EIP712: (1, 260, 190), + SettingID.DEBUG_DATA: (2, 260, 90), + SettingID.EIP7702: (2, 260, 190), + SettingID.DISPLAY_HASH: (3, 260, 90), + }, + DeviceType.APEX_M: { + SettingID.TRANSACTION_CHECKS: (0, 260, 90), + SettingID.BLIND_SIGNING: (0, 260, 235), + SettingID.NONCE: (1, 260, 90), + SettingID.VERBOSE_EIP712: (1, 260, 190), + SettingID.DEBUG_DATA: (2, 260, 90), + SettingID.EIP7702: (2, 260, 190), + SettingID.DISPLAY_HASH: (3, 260, 90), + }, } diff --git a/client/src/ledger_app_clients/ethereum/tlv.py b/client/src/ledger_app_clients/ethereum/tlv.py index 772d35654..a78830b10 100644 --- a/client/src/ledger_app_clients/ethereum/tlv.py +++ b/client/src/ledger_app_clients/ethereum/tlv.py @@ -28,6 +28,9 @@ class FieldTag(IntEnum): TX_CHECKS_PROVIDER_MSG = 0x82 TX_CHECKS_TINY_URL = 0x83 TX_CHECKS_SIMULATION_TYPE = 0x84 + THRESHOLD = 0xa0, + SIGNERS_COUNT = 0xa1, + LESM_ROLE = 0xa2, class TlvSerializable: diff --git a/doc/ethapp.adoc b/doc/ethapp.adoc index d1ce45503..a85d8cfa7 100644 --- a/doc/ethapp.adoc +++ b/doc/ethapp.adoc @@ -41,6 +41,7 @@ The following APDUs are managed by the application. They are detailed in the fol | PROVIDE NETWORK INFORMATION | 0x30 | PROVIDE TX SIMULATION | 0x32 | SIGN EIP 7702 AUTHORIZATION | 0x34 +| PROVIDE SAFE ACCOUNT | 0x36 |============================================================================================================================== @@ -836,7 +837,7 @@ The next filter should be marked as discarded (with P1) to be able to use this g ##### Message info This command should come right after the implementation of the domain has been sent with *SEND STRUCT IMPLEMENTATION*, just before sending the message implementation. -The first byte is used so that a signature of one type cannot be valid as another type. +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. The signature is computed on : @@ -845,7 +846,7 @@ The signature is computed on : ##### Amount-join token This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). -The first byte is used so that a signature of one type cannot be valid as another type. +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. The signature is computed on : @@ -854,7 +855,7 @@ The signature is computed on : ##### Amount-join value This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). -The first byte is used so that a signature of one type cannot be valid as another type. +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. A token index of 0xFF indicates the token address is in the _verifyingContract_ field of the EIP712Domain so the app won't receive an amount-join token filtering APDU. This enables support for Permit (ERC-2612) messages. @@ -865,7 +866,7 @@ The signature is computed on : ##### Date / Time This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). -The first byte is used so that a signature of one type cannot be valid as another type. +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. The signature is computed on : @@ -874,16 +875,81 @@ The signature is computed on : ##### Trusted name This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). -The first byte is used so that a signature of one type cannot be valid as another type. +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. The signature is computed on : 44 || chain ID (BE) || contract address || schema hash || field path || display name || name types || name sources +##### Calldata info + +This command should come before the first other calldata filter of the same calldata index. +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. + +The signature is not computed on a field path, because this is not tied to a field within the message and is valid as long as the app receives it during the EIP-712 flow and before any other calldata filter. + +The signature is computed on : + +55 || chain ID (BE) || contract address || schema hash || calldata index || filter flags + +##### Calldata value + +This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. + +The signature is computed on : + +66 || chain ID (BE) || contract address || schema hash || field path || calldata index + +##### Calldata callee + +This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. + +The signature is computed on : + +77 || chain ID (BE) || contract address || schema hash || field path || calldata index + +##### Calldata chain ID + +This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. + +The signature is computed on : + +88 || chain ID (BE) || contract address || schema hash || field path || calldata index + +##### Calldata selector + +This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. + +The signature is computed on : + +99 || chain ID (BE) || contract address || schema hash || field path || calldata index + +##### Calldata amount + +This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. + +The signature is computed on : + +110 || chain ID (BE) || contract address || schema hash || field path || calldata index + +##### Calldata spender + +This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. + +The signature is computed on : + +121 || chain ID (BE) || contract address || schema hash || field path || calldata index + ##### Show raw field This command should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones). -The first byte is used so that a signature of one type cannot be valid as another type. +The first byte is used as a magic number so that a signature of one type cannot be valid as another type. The signature is computed on : @@ -904,6 +970,20 @@ _Command_ 0F : message info + F4 : calldata spender + + F5 : calldata amount + + F6 : calldata selector + + F7 : calldata chain ID + + F8 : calldata callee + + F9 : calldata value + + FA : calldata info + FB : trusted name FC : date/time @@ -943,6 +1023,97 @@ None | Signature | variable |========================================== +##### If P2 == calldata info + +The calldata index is there to differentiate calldatas if the message contains multiple and if they are presented in a +way where the filters would be intertwined (the app would start receiving filters about a second calldata before +receiving all the filters from the first one). + +This command is not counted towards the `Filters count` of the `message info` command, but other calldata commands are. + +[width="80%"] +|==================================================================== +| *Description* | *Type* | *Length (byte)* +| Calldata index | uint8 | 1 +| Value filter flag | bool | 1 +| Callee filter flag | `CalldataParamPresence` | 1 +| Chain ID filter flag | bool | 1 +| Selector filter flag | bool | 1 +| Amount filter flag | bool | 1 +| Spender filter flag | `CalldataParamPresence` | 1 +| Signature length | bool | 1 +| Signature | bool | variable +|==================================================================== + +enum CalldataParamPresence +|========================================================= +| *Name* | *integer value* +| None | 0 +| Present (filtered message field) | 1 +| Present (domain's `verifyingContract`) | 2 +|========================================================= + + +##### If P2 == calldata value + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| Calldata index | 1 +| Signature length | 1 +| Signature | variable +|========================================== + +##### If P2 == calldata callee + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| Calldata index | 1 +| Signature length | 1 +| Signature | variable +|========================================== + +##### If P2 == calldata chain ID + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| Calldata index | 1 +| Signature length | 1 +| Signature | variable +|========================================== + +##### If P2 == calldata selector + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| Calldata index | 1 +| Signature length | 1 +| Signature | variable +|========================================== + +##### If P2 == calldata amount + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| Calldata index | 1 +| Signature length | 1 +| Signature | variable +|========================================== + +##### If P2 == calldata spender + +[width="80%"] +|========================================== +| *Description* | *Length (byte)* +| Calldata index | 1 +| Signature length | 1 +| Signature | variable +|========================================== + ##### If P2 == trusted name [width="80%"] @@ -1457,6 +1628,82 @@ _Output data_ | s | 32 |============================================================================================================================== +### PROVIDE SAFE ACCOUNT + +#### Description + +This command provides the Safe Account descriptors. + +The descriptors are then presented to the user to validate the Transaction Signers. + +There are 2 sub-commands: + +- One command to send the Safe descriptor +- One command to send the Signers descriptors + +> Notes: The `Safe descriptor` should be sent only once, and *before* the Signers descriptors + +The information is sent in TLV (Tag-Length-Value) mode. + +#### Coding + +_Command_ + +[width="80%"] +|============================================================================================================================== +| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* +| E0 | 36 | 00 : first chunk + + 01 : following chunk + | 00 : Safe descriptor + + 01 : Signer descriptor | variable | variable +|============================================================================================================================== + +_Input data_ + +##### If P2 == Safe Account info descriptor + +###### If P1 == first chunk + +[width="80%"] +|==================================================================== +| *Description* | *Length (byte)* +| Payload length | 2 +| link:tlv_structs.md#safe_descriptor[SAFE_DESCRIPTOR struct] | variable +|==================================================================== + +###### If P1 == following chunk + +[width="80%"] +|==================================================================== +| *Description* | *Length (byte)* +| link:tlv_structs.md#safe_descriptor[SAFE_DESCRIPTOR struct] | variable +|==================================================================== + +##### If P2 == Signer info descriptor + +###### If P1 == first chunk + +[width="80%"] +|==================================================================== +| *Description* | *Length (byte)* +| Payload length | 2 +| link:tlv_structs.md#signer_descriptor[SIGNER_DESCRIPTOR struct] | variable +|==================================================================== + +###### If P1 == following chunk + +[width="80%"] +|==================================================================== +| *Description* | *Length (byte)* +| link:tlv_structs.md#signer_descriptor[SIGNER_DESCRIPTOR struct] | variable +|==================================================================== + +_Output data_ + +None + ## Transport protocol ### General transport description diff --git a/doc/gcs.md b/doc/gcs.md index 58be85742..d2d0367f2 100644 --- a/doc/gcs.md +++ b/doc/gcs.md @@ -1,5 +1,7 @@ # Generic Clear-Signing +## Implementation + ```mermaid sequenceDiagram participant HW as Hardware Wallet @@ -21,3 +23,40 @@ sequenceDiagram note over HW: display all the
formatted fields HW ->> SW: OK (with r,s,v) / KO ``` + +## The case of nested calldatas + +```mermaid +sequenceDiagram + participant HW as Hardware Wallet + participant SW as Software Wallet + + SW ->> HW: SIGN, store only + note over HW: store compressed
calldata in RAM + HW ->> SW: OK / KO + SW ->> HW: TRANSACTION INFO (ROOT) + HW ->> SW: OK / KO + + SW ->> HW: TX FIELD DESCRIPTION (RAW) + HW ->> SW: OK / KO + + SW ->> HW: TX FIELD DESCRIPTION (CALLDATA) + activate HW + note left of HW: push into linked list of nested calldatas + HW ->> SW: OK / KO + + SW ->> HW: NESTED - TRANSACTION INFO + HW ->> SW: OK / KO + + SW ->> HW: NESTED - TX FIELD DESCRIPTION (AMOUNT) + HW ->> SW: OK / KO + deactivate HW + + SW ->> HW: TX FIELD DESCRIPTION (DATETIME) + HW ->> SW: OK / KO + + SW ->> HW: SIGN, start flow + note left of HW: check computed fields hash + note over HW: display all the
formatted fields + HW ->> SW: OK (with r,s,v) / KO +``` diff --git a/doc/tlv_structs.md b/doc/tlv_structs.md index e433c49e8..26f94a0ad 100644 --- a/doc/tlv_structs.md +++ b/doc/tlv_structs.md @@ -38,10 +38,6 @@ | NAME | 0x06 | char[] | enum entry name (ASCII) | | `$.metadata.enums...name` | | SIGNATURE | 0xff | uint8[] | signature of all the other struct fields | | computed by CAL | -> [!CAUTION] -> -> - `NAME` max length ? - ## FIELD It contains no signature since the signed TRANSACTION_INFO struct already has a hash of all the FIELD @@ -70,10 +66,6 @@ with `ParamType` enum defined as: | CALLDATA | 0x09 | | TOKEN | 0x0a | -> [!CAUTION] -> -> - `NAME` max length ? - ### PARAM_RAW | Name | Tag | Payload type | Description | Optional | Source / value | @@ -81,10 +73,6 @@ with `ParamType` enum defined as: | VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | | VALUE | 0x01 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | -> [!CAUTION] -> -> - not possible to provide static value ? - ### PARAM_AMOUNT | Name | Tag | Payload type | Description | Optional | Source / value | @@ -105,11 +93,6 @@ with `ParamType` enum defined as: This struct can contain `NATIVE_CURRENCY` multiple times for multiple addresses. -> [!CAUTION] -> -> - `NATIVE_CURRENCY` max count ? -> - `ABOVE_THRESHOLD_MSG` max length ? - ### PARAM_NFT | Name | Tag | Payload type | Description | Optional | Source / value | @@ -143,10 +126,6 @@ This struct can contain `NATIVE_CURRENCY` multiple times for multiple addresses. | DECIMALS | 0x03 | uint8 | defaults to 0 | x | `$.display.formats..fields.[].params.decimals` | | PREFIX | 0x04 | bool | defaults to false | x | `$.display.formats..fields.[].params.prefix` | -> [!CAUTION] -> -> - `BASE` max length ? - ### PARAM_ENUM | Name | Tag | Payload type | Description | Optional | Source / value | @@ -155,10 +134,6 @@ This struct can contain `NATIVE_CURRENCY` multiple times for multiple addresses. | ID | 0x01 | uint8 | | | | | VALUE | 0x02 | VALUE | reference to value to display | | `$.display.formats..fields.[].path` | -> [!CAUTION] -> -> - needs reference to enum ? - ### PARAM_TRUSTED_NAME | Name | Tag | Payload type | Description | Optional | Source / value | @@ -194,9 +169,17 @@ and `TrustedNameSource` enum defined as: | DNS | 0x05 | DNS | | DYNAMIC_RESOLVER | 0x06 | Dynamic Resolver | -> [!CAUTION] -> -> - `SOURCES` array max length ? +### PARAM_CALLDATA + +| Name | Tag | Payload type | Description | Optional | Source / value | +|-----------------|------|--------------|-----------------------------------------|----------|----------------------------------------------------------------------------------| +| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` | +| VALUE | 0x01 | VALUE | | | | +| CALLEE | 0x02 | VALUE | | | | +| CHAIN_ID | 0x03 | VALUE | | x | | +| SELECTOR | 0x04 | VALUE | | x | | +| AMOUNT | 0x05 | VALUE | | x | | +| SPENDER | 0x06 | VALUE | | x | | ### PARAM_TOKEN @@ -255,10 +238,6 @@ with `TypeFamily` enum defined as: | BYTES | 0x07 | | STRING | 0x08 | -> [!CAUTION] -> -> - `PATH` max allowed length ? - ### DATA_PATH | Name | Tag | Payload type | Description | Optional | Source / value | @@ -291,10 +270,6 @@ In version 1 of the protocol: - in last position of the path - previous element is `ARRAY_LEAF` or `DYNAMIC_LEAF` with `TYPE_FAMILY` = `BYTES` or `STRING` -> [!CAUTION] -> -> - What about [non-standard packed mode](https://docs.soliditylang.org/en/latest/abi-spec.html#non-standard-packed-mode) ? - ### ARRAY_ELEMENT | Name | Tag | Payload type | Description | Optional | Source / value | @@ -393,3 +368,37 @@ The _Simulation Type_ is normalized and interpreted like this: - `0`: Transaction - `1`: Typed Data (EIP-712) - `2`: Personal Message (EIP-191) + +## SAFE_ACCOUNT + +### SAFE_DESCRIPTOR + +| Name | Tag | Payload type | Description | Value | +|-------------------|------|--------------|--------------------------------|-----------------------------------| +| STRUCTURE_TYPE | 0x01 | uint8 | Structure type | `0x27` (`TYPE_LESM_ACCOUNT_INFO`) | +| STRUCTURE_VERSION | 0x02 | uint8 | Structure version | `0x01` | +| CHALLENGE | 0x14 | uint32 | Challenge generated by the App | | +| ADDRESS | 0x22 | uint8[20] | Safe Account Address | | +| THRESHOLD | 0xA0 | uint8 | Number of required signatures | | +| SIGNERS_COUNT | 0xA1 | uint8 | Total number of signers | | +| ROLE | 0xA2 | uint8 | Role of the account | | +| SIGNATURE | 0x15 | uint8[] | Signature of the structure | | + +The signature is computed on the full payload data, using `CX_CURVE_SECP256K1`. + +The _Role_ is normalized and interpreted like this: + +- `0`: Signer +- `1`: Proposer + +### SIGNER_DESCRIPTOR + +| Name | Tag | Payload type | Description | Value | +|-------------------|------|--------------|--------------------------------|------------------------------------| +| STRUCTURE_TYPE | 0x01 | uint8 | Structure type | `0x0A` (`TYPE_VERIFIABLE_ADDRESS`) | +| STRUCTURE_VERSION | 0x02 | uint8 | Structure version | `0x01` | +| CHALLENGE | 0x14 | uint32 | Challenge generated by the App | | +| ADDRESS | 0x22 | uint8[20] | Signer Address | | +| SIGNATURE | 0x15 | uint8[] | Signature of the structure | | + +The signature is computed on the full payload data, using `CX_CURVE_SECP256K1`. diff --git a/ethereum-plugin-sdk b/ethereum-plugin-sdk index 99d7871a1..dda423015 160000 --- a/ethereum-plugin-sdk +++ b/ethereum-plugin-sdk @@ -1 +1 @@ -Subproject commit 99d7871a13cae92c4ca65b5bcfd9a800f8056463 +Subproject commit dda423015f2edfdabae9a0eb105fe0a41fe04d97 diff --git a/glyphs/chain_100_48px.gif b/glyphs/chain_100_48px.gif new file mode 100644 index 000000000..d00f79128 Binary files /dev/null and b/glyphs/chain_100_48px.gif differ diff --git a/glyphs/chain_10200_48px.gif b/glyphs/chain_10200_48px.gif new file mode 100644 index 000000000..d00f79128 Binary files /dev/null and b/glyphs/chain_10200_48px.gif differ diff --git a/glyphs/chain_1030_48px.gif b/glyphs/chain_1030_48px.gif new file mode 100644 index 000000000..e29aefcc3 Binary files /dev/null and b/glyphs/chain_1030_48px.gif differ diff --git a/glyphs/chain_10507_48px.gif b/glyphs/chain_10507_48px.gif new file mode 100644 index 000000000..ddd18f4f2 Binary files /dev/null and b/glyphs/chain_10507_48px.gif differ diff --git a/glyphs/chain_106_48px.gif b/glyphs/chain_106_48px.gif new file mode 100644 index 000000000..3b699aa9a Binary files /dev/null and b/glyphs/chain_106_48px.gif differ diff --git a/glyphs/chain_1088_48px.gif b/glyphs/chain_1088_48px.gif new file mode 100644 index 000000000..610e2ac25 Binary files /dev/null and b/glyphs/chain_1088_48px.gif differ diff --git a/glyphs/chain_108_48px.gif b/glyphs/chain_108_48px.gif new file mode 100644 index 000000000..13a53a9ab Binary files /dev/null and b/glyphs/chain_108_48px.gif differ diff --git a/glyphs/chain_10_48px.gif b/glyphs/chain_10_48px.gif new file mode 100644 index 000000000..6473decf0 Binary files /dev/null and b/glyphs/chain_10_48px.gif differ diff --git a/glyphs/chain_1101_48px.gif b/glyphs/chain_1101_48px.gif new file mode 100644 index 000000000..aa118523c Binary files /dev/null and b/glyphs/chain_1101_48px.gif differ diff --git a/glyphs/chain_11155111_48px.gif b/glyphs/chain_11155111_48px.gif new file mode 100644 index 000000000..bdc1cf4fb Binary files /dev/null and b/glyphs/chain_11155111_48px.gif differ diff --git a/glyphs/chain_11155420_48px.gif b/glyphs/chain_11155420_48px.gif new file mode 100644 index 000000000..6473decf0 Binary files /dev/null and b/glyphs/chain_11155420_48px.gif differ diff --git a/glyphs/chain_1116_48px.gif b/glyphs/chain_1116_48px.gif new file mode 100644 index 000000000..573ad4b91 Binary files /dev/null and b/glyphs/chain_1116_48px.gif differ diff --git a/glyphs/chain_11297108109_48px.gif b/glyphs/chain_11297108109_48px.gif new file mode 100644 index 000000000..4b7aed954 Binary files /dev/null and b/glyphs/chain_11297108109_48px.gif differ diff --git a/glyphs/chain_1135_48px.gif b/glyphs/chain_1135_48px.gif new file mode 100644 index 000000000..9f58760be Binary files /dev/null and b/glyphs/chain_1135_48px.gif differ diff --git a/glyphs/chain_1284_48px.gif b/glyphs/chain_1284_48px.gif new file mode 100644 index 000000000..f54f7e987 Binary files /dev/null and b/glyphs/chain_1284_48px.gif differ diff --git a/glyphs/chain_1285_48px.gif b/glyphs/chain_1285_48px.gif new file mode 100644 index 000000000..224517304 Binary files /dev/null and b/glyphs/chain_1285_48px.gif differ diff --git a/glyphs/chain_1313114_48px.gif b/glyphs/chain_1313114_48px.gif new file mode 100644 index 000000000..08fa03a6b Binary files /dev/null and b/glyphs/chain_1313114_48px.gif differ diff --git a/glyphs/chain_137_48px.gif b/glyphs/chain_137_48px.gif new file mode 100644 index 000000000..aa118523c Binary files /dev/null and b/glyphs/chain_137_48px.gif differ diff --git a/glyphs/chain_138_48px.gif b/glyphs/chain_138_48px.gif new file mode 100644 index 000000000..db20a8460 Binary files /dev/null and b/glyphs/chain_138_48px.gif differ diff --git a/glyphs/chain_146_48px.gif b/glyphs/chain_146_48px.gif new file mode 100644 index 000000000..989bbb613 Binary files /dev/null and b/glyphs/chain_146_48px.gif differ diff --git a/glyphs/chain_14_48px.gif b/glyphs/chain_14_48px.gif new file mode 100644 index 000000000..b1c5dfab0 Binary files /dev/null and b/glyphs/chain_14_48px.gif differ diff --git a/glyphs/chain_153153_48px.gif b/glyphs/chain_153153_48px.gif new file mode 100644 index 000000000..a3d812fe5 Binary files /dev/null and b/glyphs/chain_153153_48px.gif differ diff --git a/glyphs/chain_1620_48px.gif b/glyphs/chain_1620_48px.gif new file mode 100644 index 000000000..e1efe2de2 Binary files /dev/null and b/glyphs/chain_1620_48px.gif differ diff --git a/glyphs/chain_1666600000_48px.gif b/glyphs/chain_1666600000_48px.gif new file mode 100644 index 000000000..79a585caf Binary files /dev/null and b/glyphs/chain_1666600000_48px.gif differ diff --git a/glyphs/chain_1666600001_48px.gif b/glyphs/chain_1666600001_48px.gif new file mode 100644 index 000000000..79a585caf Binary files /dev/null and b/glyphs/chain_1666600001_48px.gif differ diff --git a/glyphs/chain_168587773_48px.gif b/glyphs/chain_168587773_48px.gif new file mode 100644 index 000000000..6b6c1ccfe Binary files /dev/null and b/glyphs/chain_168587773_48px.gif differ diff --git a/glyphs/chain_16_48px.gif b/glyphs/chain_16_48px.gif new file mode 100644 index 000000000..7341e3aa9 Binary files /dev/null and b/glyphs/chain_16_48px.gif differ diff --git a/glyphs/chain_17000_48px.gif b/glyphs/chain_17000_48px.gif new file mode 100644 index 000000000..bdc1cf4fb Binary files /dev/null and b/glyphs/chain_17000_48px.gif differ diff --git a/glyphs/chain_1818_48px.gif b/glyphs/chain_1818_48px.gif new file mode 100644 index 000000000..1f99a6e3b Binary files /dev/null and b/glyphs/chain_1818_48px.gif differ diff --git a/glyphs/chain_1868_48px.gif b/glyphs/chain_1868_48px.gif new file mode 100644 index 000000000..e8426ee95 Binary files /dev/null and b/glyphs/chain_1868_48px.gif differ diff --git a/glyphs/chain_1907_48px.gif b/glyphs/chain_1907_48px.gif new file mode 100644 index 000000000..b8f86ed03 Binary files /dev/null and b/glyphs/chain_1907_48px.gif differ diff --git a/glyphs/chain_1923_48px.gif b/glyphs/chain_1923_48px.gif new file mode 100644 index 000000000..5dc9f62f0 Binary files /dev/null and b/glyphs/chain_1923_48px.gif differ diff --git a/glyphs/chain_1924_48px.gif b/glyphs/chain_1924_48px.gif new file mode 100644 index 000000000..5dc9f62f0 Binary files /dev/null and b/glyphs/chain_1924_48px.gif differ diff --git a/glyphs/chain_1946_48px.gif b/glyphs/chain_1946_48px.gif new file mode 100644 index 000000000..e8426ee95 Binary files /dev/null and b/glyphs/chain_1946_48px.gif differ diff --git a/glyphs/chain_196_48px.gif b/glyphs/chain_196_48px.gif new file mode 100644 index 000000000..4aadedd9d Binary files /dev/null and b/glyphs/chain_196_48px.gif differ diff --git a/glyphs/chain_1987_48px.gif b/glyphs/chain_1987_48px.gif new file mode 100644 index 000000000..40cd56ffd Binary files /dev/null and b/glyphs/chain_1987_48px.gif differ diff --git a/glyphs/chain_199_48px.gif b/glyphs/chain_199_48px.gif new file mode 100644 index 000000000..6e80a1d37 Binary files /dev/null and b/glyphs/chain_199_48px.gif differ diff --git a/glyphs/chain_19_48px.gif b/glyphs/chain_19_48px.gif new file mode 100644 index 000000000..0c0f05677 Binary files /dev/null and b/glyphs/chain_19_48px.gif differ diff --git a/glyphs/chain_1_48px.gif b/glyphs/chain_1_48px.gif new file mode 100644 index 000000000..2893b7115 Binary files /dev/null and b/glyphs/chain_1_48px.gif differ diff --git a/glyphs/chain_200625_48px.gif b/glyphs/chain_200625_48px.gif new file mode 100644 index 000000000..c3306c742 Binary files /dev/null and b/glyphs/chain_200625_48px.gif differ diff --git a/glyphs/chain_200810_48px.gif b/glyphs/chain_200810_48px.gif new file mode 100644 index 000000000..b764df72f Binary files /dev/null and b/glyphs/chain_200810_48px.gif differ diff --git a/glyphs/chain_200901_48px.gif b/glyphs/chain_200901_48px.gif new file mode 100644 index 000000000..b764df72f Binary files /dev/null and b/glyphs/chain_200901_48px.gif differ diff --git a/glyphs/chain_20531811_48px.gif b/glyphs/chain_20531811_48px.gif new file mode 100644 index 000000000..2e78d6ea6 Binary files /dev/null and b/glyphs/chain_20531811_48px.gif differ diff --git a/glyphs/chain_20531812_48px.gif b/glyphs/chain_20531812_48px.gif new file mode 100644 index 000000000..2e78d6ea6 Binary files /dev/null and b/glyphs/chain_20531812_48px.gif differ diff --git a/glyphs/chain_2222_48px.gif b/glyphs/chain_2222_48px.gif new file mode 100644 index 000000000..ef3915890 Binary files /dev/null and b/glyphs/chain_2222_48px.gif differ diff --git a/glyphs/chain_237_48px.gif b/glyphs/chain_237_48px.gif new file mode 100644 index 000000000..253dc0aff Binary files /dev/null and b/glyphs/chain_237_48px.gif differ diff --git a/glyphs/chain_24484_48px.gif b/glyphs/chain_24484_48px.gif new file mode 100644 index 000000000..4c385b33c Binary files /dev/null and b/glyphs/chain_24484_48px.gif differ diff --git a/glyphs/chain_245022926_48px.gif b/glyphs/chain_245022926_48px.gif new file mode 100644 index 000000000..939e73a90 Binary files /dev/null and b/glyphs/chain_245022926_48px.gif differ diff --git a/glyphs/chain_245022934_48px.gif b/glyphs/chain_245022934_48px.gif new file mode 100644 index 000000000..939e73a90 Binary files /dev/null and b/glyphs/chain_245022934_48px.gif differ diff --git a/glyphs/chain_246529_48px.gif b/glyphs/chain_246529_48px.gif new file mode 100644 index 000000000..776ef6bf9 Binary files /dev/null and b/glyphs/chain_246529_48px.gif differ diff --git a/glyphs/chain_246_48px.gif b/glyphs/chain_246_48px.gif new file mode 100644 index 000000000..43cc952db Binary files /dev/null and b/glyphs/chain_246_48px.gif differ diff --git a/glyphs/chain_248_48px.gif b/glyphs/chain_248_48px.gif new file mode 100644 index 000000000..d209a5f1d Binary files /dev/null and b/glyphs/chain_248_48px.gif differ diff --git a/glyphs/chain_24_48px.gif b/glyphs/chain_24_48px.gif new file mode 100644 index 000000000..101d7d466 Binary files /dev/null and b/glyphs/chain_24_48px.gif differ diff --git a/glyphs/chain_250_48px.gif b/glyphs/chain_250_48px.gif new file mode 100644 index 000000000..e538ac9e8 Binary files /dev/null and b/glyphs/chain_250_48px.gif differ diff --git a/glyphs/chain_25_48px.gif b/glyphs/chain_25_48px.gif new file mode 100644 index 000000000..ce4a34b58 Binary files /dev/null and b/glyphs/chain_25_48px.gif differ diff --git a/glyphs/chain_269_48px.gif b/glyphs/chain_269_48px.gif new file mode 100644 index 000000000..1f97ed486 Binary files /dev/null and b/glyphs/chain_269_48px.gif differ diff --git a/glyphs/chain_288_48px.gif b/glyphs/chain_288_48px.gif new file mode 100644 index 000000000..fa4bc2f3e Binary files /dev/null and b/glyphs/chain_288_48px.gif differ diff --git a/glyphs/chain_2894_48px.gif b/glyphs/chain_2894_48px.gif new file mode 100644 index 000000000..30d5880a7 Binary files /dev/null and b/glyphs/chain_2894_48px.gif differ diff --git a/glyphs/chain_2_48px.gif b/glyphs/chain_2_48px.gif new file mode 100644 index 000000000..de532a7f3 Binary files /dev/null and b/glyphs/chain_2_48px.gif differ diff --git a/glyphs/chain_300_48px.gif b/glyphs/chain_300_48px.gif new file mode 100644 index 000000000..ba147fa3d Binary files /dev/null and b/glyphs/chain_300_48px.gif differ diff --git a/glyphs/chain_30_48px.gif b/glyphs/chain_30_48px.gif new file mode 100644 index 000000000..c31a5d29f Binary files /dev/null and b/glyphs/chain_30_48px.gif differ diff --git a/glyphs/chain_31102_48px.gif b/glyphs/chain_31102_48px.gif new file mode 100644 index 000000000..e4976fcc2 Binary files /dev/null and b/glyphs/chain_31102_48px.gif differ diff --git a/glyphs/chain_3125659152_48px.gif b/glyphs/chain_3125659152_48px.gif new file mode 100644 index 000000000..2a4921258 Binary files /dev/null and b/glyphs/chain_3125659152_48px.gif differ diff --git a/glyphs/chain_31_48px.gif b/glyphs/chain_31_48px.gif new file mode 100644 index 000000000..c31a5d29f Binary files /dev/null and b/glyphs/chain_31_48px.gif differ diff --git a/glyphs/chain_321_48px.gif b/glyphs/chain_321_48px.gif new file mode 100644 index 000000000..84cf4c6c6 Binary files /dev/null and b/glyphs/chain_321_48px.gif differ diff --git a/glyphs/chain_324_48px.gif b/glyphs/chain_324_48px.gif new file mode 100644 index 000000000..ba147fa3d Binary files /dev/null and b/glyphs/chain_324_48px.gif differ diff --git a/glyphs/chain_336_48px.gif b/glyphs/chain_336_48px.gif new file mode 100644 index 000000000..2560a7250 Binary files /dev/null and b/glyphs/chain_336_48px.gif differ diff --git a/glyphs/chain_369_48px.gif b/glyphs/chain_369_48px.gif new file mode 100644 index 000000000..2911de85d Binary files /dev/null and b/glyphs/chain_369_48px.gif differ diff --git a/glyphs/chain_3776_48px.gif b/glyphs/chain_3776_48px.gif new file mode 100644 index 000000000..aae5e5c03 Binary files /dev/null and b/glyphs/chain_3776_48px.gif differ diff --git a/glyphs/chain_39797_48px.gif b/glyphs/chain_39797_48px.gif new file mode 100644 index 000000000..588a3cdb1 Binary files /dev/null and b/glyphs/chain_39797_48px.gif differ diff --git a/glyphs/chain_3_48px.gif b/glyphs/chain_3_48px.gif new file mode 100644 index 000000000..bdc1cf4fb Binary files /dev/null and b/glyphs/chain_3_48px.gif differ diff --git a/glyphs/chain_401697_48px.gif b/glyphs/chain_401697_48px.gif new file mode 100644 index 000000000..aecd9f261 Binary files /dev/null and b/glyphs/chain_401697_48px.gif differ diff --git a/glyphs/chain_40_48px.gif b/glyphs/chain_40_48px.gif new file mode 100644 index 000000000..0204c1583 Binary files /dev/null and b/glyphs/chain_40_48px.gif differ diff --git a/glyphs/chain_4201_48px.gif b/glyphs/chain_4201_48px.gif new file mode 100644 index 000000000..3e417c763 Binary files /dev/null and b/glyphs/chain_4201_48px.gif differ diff --git a/glyphs/chain_4202_48px.gif b/glyphs/chain_4202_48px.gif new file mode 100644 index 000000000..9f58760be Binary files /dev/null and b/glyphs/chain_4202_48px.gif differ diff --git a/glyphs/chain_421614_48px.gif b/glyphs/chain_421614_48px.gif new file mode 100644 index 000000000..0d00abe3e Binary files /dev/null and b/glyphs/chain_421614_48px.gif differ diff --git a/glyphs/chain_42161_48px.gif b/glyphs/chain_42161_48px.gif new file mode 100644 index 000000000..0d00abe3e Binary files /dev/null and b/glyphs/chain_42161_48px.gif differ diff --git a/glyphs/chain_42220_48px.gif b/glyphs/chain_42220_48px.gif new file mode 100644 index 000000000..5ae960982 Binary files /dev/null and b/glyphs/chain_42220_48px.gif differ diff --git a/glyphs/chain_42793_48px.gif b/glyphs/chain_42793_48px.gif new file mode 100644 index 000000000..107eeb91c Binary files /dev/null and b/glyphs/chain_42793_48px.gif differ diff --git a/glyphs/chain_42_48px.gif b/glyphs/chain_42_48px.gif new file mode 100644 index 000000000..3e417c763 Binary files /dev/null and b/glyphs/chain_42_48px.gif differ diff --git a/glyphs/chain_43114_48px.gif b/glyphs/chain_43114_48px.gif new file mode 100644 index 000000000..b764713de Binary files /dev/null and b/glyphs/chain_43114_48px.gif differ diff --git a/glyphs/chain_44787_48px.gif b/glyphs/chain_44787_48px.gif new file mode 100644 index 000000000..5ae960982 Binary files /dev/null and b/glyphs/chain_44787_48px.gif differ diff --git a/glyphs/chain_4689_48px.gif b/glyphs/chain_4689_48px.gif new file mode 100644 index 000000000..3dce2761f Binary files /dev/null and b/glyphs/chain_4689_48px.gif differ diff --git a/glyphs/chain_4689_64px.gif b/glyphs/chain_4689_64px.gif index 07830f267..4757ffb26 100644 Binary files a/glyphs/chain_4689_64px.gif and b/glyphs/chain_4689_64px.gif differ diff --git a/glyphs/chain_4690_48px.gif b/glyphs/chain_4690_48px.gif new file mode 100644 index 000000000..813c237b8 Binary files /dev/null and b/glyphs/chain_4690_48px.gif differ diff --git a/glyphs/chain_47763_48px.gif b/glyphs/chain_47763_48px.gif new file mode 100644 index 000000000..b2755d9fb Binary files /dev/null and b/glyphs/chain_47763_48px.gif differ diff --git a/glyphs/chain_4919_48px.gif b/glyphs/chain_4919_48px.gif new file mode 100644 index 000000000..1562414cd Binary files /dev/null and b/glyphs/chain_4919_48px.gif differ diff --git a/glyphs/chain_4_48px.gif b/glyphs/chain_4_48px.gif new file mode 100644 index 000000000..bdc1cf4fb Binary files /dev/null and b/glyphs/chain_4_48px.gif differ diff --git a/glyphs/chain_5000_48px.gif b/glyphs/chain_5000_48px.gif new file mode 100644 index 000000000..48f098b2a Binary files /dev/null and b/glyphs/chain_5000_48px.gif differ diff --git a/glyphs/chain_5003_48px.gif b/glyphs/chain_5003_48px.gif new file mode 100644 index 000000000..48f098b2a Binary files /dev/null and b/glyphs/chain_5003_48px.gif differ diff --git a/glyphs/chain_50_48px.gif b/glyphs/chain_50_48px.gif new file mode 100644 index 000000000..aedad62d5 Binary files /dev/null and b/glyphs/chain_50_48px.gif differ diff --git a/glyphs/chain_5165_48px.gif b/glyphs/chain_5165_48px.gif new file mode 100644 index 000000000..10a299c50 Binary files /dev/null and b/glyphs/chain_5165_48px.gif differ diff --git a/glyphs/chain_51_48px.gif b/glyphs/chain_51_48px.gif new file mode 100644 index 000000000..5f7ab06a3 Binary files /dev/null and b/glyphs/chain_51_48px.gif differ diff --git a/glyphs/chain_5201420_48px.gif b/glyphs/chain_5201420_48px.gif new file mode 100644 index 000000000..056f668fb Binary files /dev/null and b/glyphs/chain_5201420_48px.gif differ diff --git a/glyphs/chain_52014_48px.gif b/glyphs/chain_52014_48px.gif new file mode 100644 index 000000000..056f668fb Binary files /dev/null and b/glyphs/chain_52014_48px.gif differ diff --git a/glyphs/chain_534351_48px.gif b/glyphs/chain_534351_48px.gif new file mode 100644 index 000000000..d4827270c Binary files /dev/null and b/glyphs/chain_534351_48px.gif differ diff --git a/glyphs/chain_534352_48px.gif b/glyphs/chain_534352_48px.gif new file mode 100644 index 000000000..d4827270c Binary files /dev/null and b/glyphs/chain_534352_48px.gif differ diff --git a/glyphs/chain_534353_48px.gif b/glyphs/chain_534353_48px.gif new file mode 100644 index 000000000..d4827270c Binary files /dev/null and b/glyphs/chain_534353_48px.gif differ diff --git a/glyphs/chain_534354_48px.gif b/glyphs/chain_534354_48px.gif new file mode 100644 index 000000000..3bc29d561 Binary files /dev/null and b/glyphs/chain_534354_48px.gif differ diff --git a/glyphs/chain_543210_48px.gif b/glyphs/chain_543210_48px.gif new file mode 100644 index 000000000..af468f45d Binary files /dev/null and b/glyphs/chain_543210_48px.gif differ diff --git a/glyphs/chain_56_48px.gif b/glyphs/chain_56_48px.gif new file mode 100644 index 000000000..a63a5b05b Binary files /dev/null and b/glyphs/chain_56_48px.gif differ diff --git a/glyphs/chain_57_48px.gif b/glyphs/chain_57_48px.gif new file mode 100644 index 000000000..ac0939ab9 Binary files /dev/null and b/glyphs/chain_57_48px.gif differ diff --git a/glyphs/chain_59141_48px.gif b/glyphs/chain_59141_48px.gif new file mode 100644 index 000000000..7ebeb2058 Binary files /dev/null and b/glyphs/chain_59141_48px.gif differ diff --git a/glyphs/chain_59144_48px.gif b/glyphs/chain_59144_48px.gif new file mode 100644 index 000000000..7ebeb2058 Binary files /dev/null and b/glyphs/chain_59144_48px.gif differ diff --git a/glyphs/chain_592_48px.gif b/glyphs/chain_592_48px.gif new file mode 100644 index 000000000..ac234180f Binary files /dev/null and b/glyphs/chain_592_48px.gif differ diff --git a/glyphs/chain_5_48px.gif b/glyphs/chain_5_48px.gif new file mode 100644 index 000000000..00176bb8d Binary files /dev/null and b/glyphs/chain_5_48px.gif differ diff --git a/glyphs/chain_60808_48px.gif b/glyphs/chain_60808_48px.gif new file mode 100644 index 000000000..adc34f372 Binary files /dev/null and b/glyphs/chain_60808_48px.gif differ diff --git a/glyphs/chain_60_48px.gif b/glyphs/chain_60_48px.gif new file mode 100644 index 000000000..1f1d24614 Binary files /dev/null and b/glyphs/chain_60_48px.gif differ diff --git a/glyphs/chain_61_48px.gif b/glyphs/chain_61_48px.gif new file mode 120000 index 000000000..08adaeb10 --- /dev/null +++ b/glyphs/chain_61_48px.gif @@ -0,0 +1 @@ +chain_1_48px.gif \ No newline at end of file diff --git a/glyphs/chain_62320_48px.gif b/glyphs/chain_62320_48px.gif new file mode 100644 index 000000000..5ae960982 Binary files /dev/null and b/glyphs/chain_62320_48px.gif differ diff --git a/glyphs/chain_62621_48px.gif b/glyphs/chain_62621_48px.gif new file mode 100644 index 000000000..3a1f296be Binary files /dev/null and b/glyphs/chain_62621_48px.gif differ diff --git a/glyphs/chain_64_48px.gif b/glyphs/chain_64_48px.gif new file mode 100644 index 000000000..bdd1ec534 Binary files /dev/null and b/glyphs/chain_64_48px.gif differ diff --git a/glyphs/chain_66_48px.gif b/glyphs/chain_66_48px.gif new file mode 100644 index 000000000..4bc74803d Binary files /dev/null and b/glyphs/chain_66_48px.gif differ diff --git a/glyphs/chain_7000_48px.gif b/glyphs/chain_7000_48px.gif new file mode 100644 index 000000000..f7f46518d Binary files /dev/null and b/glyphs/chain_7000_48px.gif differ diff --git a/glyphs/chain_7171_48px.gif b/glyphs/chain_7171_48px.gif new file mode 100644 index 000000000..f678cd262 Binary files /dev/null and b/glyphs/chain_7171_48px.gif differ diff --git a/glyphs/chain_7341_48px.gif b/glyphs/chain_7341_48px.gif new file mode 100644 index 000000000..fa04c4827 Binary files /dev/null and b/glyphs/chain_7341_48px.gif differ diff --git a/glyphs/chain_73799_48px.gif b/glyphs/chain_73799_48px.gif new file mode 100644 index 000000000..5e9a131e0 Binary files /dev/null and b/glyphs/chain_73799_48px.gif differ diff --git a/glyphs/chain_76_48px.gif b/glyphs/chain_76_48px.gif new file mode 100644 index 000000000..139a18a69 Binary files /dev/null and b/glyphs/chain_76_48px.gif differ diff --git a/glyphs/chain_7762959_48px.gif b/glyphs/chain_7762959_48px.gif new file mode 100644 index 000000000..d1fa46706 Binary files /dev/null and b/glyphs/chain_7762959_48px.gif differ diff --git a/glyphs/chain_78_48px.gif b/glyphs/chain_78_48px.gif new file mode 100644 index 000000000..24d63abaa Binary files /dev/null and b/glyphs/chain_78_48px.gif differ diff --git a/glyphs/chain_80094_48px.gif b/glyphs/chain_80094_48px.gif new file mode 100644 index 000000000..a811c4937 Binary files /dev/null and b/glyphs/chain_80094_48px.gif differ diff --git a/glyphs/chain_81457_48px.gif b/glyphs/chain_81457_48px.gif new file mode 100644 index 000000000..6b6c1ccfe Binary files /dev/null and b/glyphs/chain_81457_48px.gif differ diff --git a/glyphs/chain_820_48px.gif b/glyphs/chain_820_48px.gif new file mode 100644 index 000000000..7206fddb3 Binary files /dev/null and b/glyphs/chain_820_48px.gif differ diff --git a/glyphs/chain_8217_48px.gif b/glyphs/chain_8217_48px.gif new file mode 100644 index 000000000..6236c6b5d Binary files /dev/null and b/glyphs/chain_8217_48px.gif differ diff --git a/glyphs/chain_82_48px.gif b/glyphs/chain_82_48px.gif new file mode 100644 index 000000000..b37c36aa1 Binary files /dev/null and b/glyphs/chain_82_48px.gif differ diff --git a/glyphs/chain_84532_48px.gif b/glyphs/chain_84532_48px.gif new file mode 100644 index 000000000..2cb62b7ef Binary files /dev/null and b/glyphs/chain_84532_48px.gif differ diff --git a/glyphs/chain_8453_48px.gif b/glyphs/chain_8453_48px.gif new file mode 100644 index 000000000..2cb62b7ef Binary files /dev/null and b/glyphs/chain_8453_48px.gif differ diff --git a/glyphs/chain_846000_48px.gif b/glyphs/chain_846000_48px.gif new file mode 100644 index 000000000..5c43a87ba Binary files /dev/null and b/glyphs/chain_846000_48px.gif differ diff --git a/glyphs/chain_888_48px.gif b/glyphs/chain_888_48px.gif new file mode 100644 index 000000000..16f3242e0 Binary files /dev/null and b/glyphs/chain_888_48px.gif differ diff --git a/glyphs/chain_88_48px.gif b/glyphs/chain_88_48px.gif new file mode 100644 index 000000000..823d5843a Binary files /dev/null and b/glyphs/chain_88_48px.gif differ diff --git a/glyphs/chain_8_48px.gif b/glyphs/chain_8_48px.gif new file mode 100644 index 000000000..79f189364 Binary files /dev/null and b/glyphs/chain_8_48px.gif differ diff --git a/glyphs/chain_9001_48px.gif b/glyphs/chain_9001_48px.gif new file mode 100644 index 000000000..8eb601321 Binary files /dev/null and b/glyphs/chain_9001_48px.gif differ diff --git a/glyphs/chain_943_48px.gif b/glyphs/chain_943_48px.gif new file mode 100644 index 000000000..2911de85d Binary files /dev/null and b/glyphs/chain_943_48px.gif differ diff --git a/glyphs/chain_994873017_48px.gif b/glyphs/chain_994873017_48px.gif new file mode 100644 index 000000000..c73cded02 Binary files /dev/null and b/glyphs/chain_994873017_48px.gif differ diff --git a/glyphs/chain_999_48px.gif b/glyphs/chain_999_48px.gif new file mode 100644 index 000000000..00d0100ab Binary files /dev/null and b/glyphs/chain_999_48px.gif differ diff --git a/glyphs/chain_99_48px.gif b/glyphs/chain_99_48px.gif new file mode 100644 index 000000000..251892036 Binary files /dev/null and b/glyphs/chain_99_48px.gif differ diff --git a/glyphs/multisig.png b/glyphs/multisig.png new file mode 100644 index 000000000..f498323b3 Binary files /dev/null and b/glyphs/multisig.png differ diff --git a/icons/apex_app_chain_1.gif b/icons/apex_app_chain_1.gif new file mode 100644 index 000000000..6f57dd01e Binary files /dev/null and b/icons/apex_app_chain_1.gif differ diff --git a/icons/apex_app_chain_108.gif b/icons/apex_app_chain_108.gif new file mode 100644 index 000000000..0af1b3f43 Binary files /dev/null and b/icons/apex_app_chain_108.gif differ diff --git a/icons/apex_app_chain_1284.gif b/icons/apex_app_chain_1284.gif new file mode 100644 index 000000000..99264af53 Binary files /dev/null and b/icons/apex_app_chain_1284.gif differ diff --git a/icons/apex_app_chain_1285.gif b/icons/apex_app_chain_1285.gif new file mode 100644 index 000000000..77d6ada12 Binary files /dev/null and b/icons/apex_app_chain_1285.gif differ diff --git a/icons/apex_app_chain_1313114.gif b/icons/apex_app_chain_1313114.gif new file mode 100644 index 000000000..5aa424bf3 Binary files /dev/null and b/icons/apex_app_chain_1313114.gif differ diff --git a/icons/apex_app_chain_146.gif b/icons/apex_app_chain_146.gif new file mode 100644 index 000000000..d26aa79b9 Binary files /dev/null and b/icons/apex_app_chain_146.gif differ diff --git a/icons/apex_app_chain_1620.gif b/icons/apex_app_chain_1620.gif new file mode 100644 index 000000000..834c1829b Binary files /dev/null and b/icons/apex_app_chain_1620.gif differ diff --git a/icons/apex_app_chain_1666600000.gif b/icons/apex_app_chain_1666600000.gif new file mode 100644 index 000000000..0d6dac5e4 Binary files /dev/null and b/icons/apex_app_chain_1666600000.gif differ diff --git a/icons/apex_app_chain_19.gif b/icons/apex_app_chain_19.gif new file mode 100644 index 000000000..20546130d Binary files /dev/null and b/icons/apex_app_chain_19.gif differ diff --git a/icons/apex_app_chain_1987.gif b/icons/apex_app_chain_1987.gif new file mode 100644 index 000000000..e038b1527 Binary files /dev/null and b/icons/apex_app_chain_1987.gif differ diff --git a/icons/apex_app_chain_2.gif b/icons/apex_app_chain_2.gif new file mode 100644 index 000000000..f1c9e5c8b Binary files /dev/null and b/icons/apex_app_chain_2.gif differ diff --git a/icons/apex_app_chain_200625.gif b/icons/apex_app_chain_200625.gif new file mode 100644 index 000000000..aedac180d Binary files /dev/null and b/icons/apex_app_chain_200625.gif differ diff --git a/icons/apex_app_chain_20531812.gif b/icons/apex_app_chain_20531812.gif new file mode 100644 index 000000000..cf55d07fd Binary files /dev/null and b/icons/apex_app_chain_20531812.gif differ diff --git a/icons/apex_app_chain_237.gif b/icons/apex_app_chain_237.gif new file mode 100644 index 000000000..67ba87931 Binary files /dev/null and b/icons/apex_app_chain_237.gif differ diff --git a/icons/apex_app_chain_24484.gif b/icons/apex_app_chain_24484.gif new file mode 100644 index 000000000..e00315814 Binary files /dev/null and b/icons/apex_app_chain_24484.gif differ diff --git a/icons/apex_app_chain_246.gif b/icons/apex_app_chain_246.gif new file mode 100644 index 000000000..966d973ee Binary files /dev/null and b/icons/apex_app_chain_246.gif differ diff --git a/icons/apex_app_chain_246529.gif b/icons/apex_app_chain_246529.gif new file mode 100644 index 000000000..862aa7244 Binary files /dev/null and b/icons/apex_app_chain_246529.gif differ diff --git a/icons/apex_app_chain_248.gif b/icons/apex_app_chain_248.gif new file mode 100644 index 000000000..5729cf9e4 Binary files /dev/null and b/icons/apex_app_chain_248.gif differ diff --git a/icons/apex_app_chain_269.gif b/icons/apex_app_chain_269.gif new file mode 100644 index 000000000..4742da814 Binary files /dev/null and b/icons/apex_app_chain_269.gif differ diff --git a/icons/apex_app_chain_2894.gif b/icons/apex_app_chain_2894.gif new file mode 100644 index 000000000..76cf60d21 Binary files /dev/null and b/icons/apex_app_chain_2894.gif differ diff --git a/icons/apex_app_chain_30.gif b/icons/apex_app_chain_30.gif new file mode 100644 index 000000000..0361a1805 Binary files /dev/null and b/icons/apex_app_chain_30.gif differ diff --git a/icons/apex_app_chain_31.gif b/icons/apex_app_chain_31.gif new file mode 120000 index 000000000..6c21a3a25 --- /dev/null +++ b/icons/apex_app_chain_31.gif @@ -0,0 +1 @@ +apex_app_chain_30.gif \ No newline at end of file diff --git a/icons/apex_app_chain_31102.gif b/icons/apex_app_chain_31102.gif new file mode 100644 index 000000000..58d0e18f5 Binary files /dev/null and b/icons/apex_app_chain_31102.gif differ diff --git a/icons/apex_app_chain_3125659152.gif b/icons/apex_app_chain_3125659152.gif new file mode 100644 index 000000000..47eb62b02 Binary files /dev/null and b/icons/apex_app_chain_3125659152.gif differ diff --git a/icons/apex_app_chain_336.gif b/icons/apex_app_chain_336.gif new file mode 100644 index 000000000..e82968996 Binary files /dev/null and b/icons/apex_app_chain_336.gif differ diff --git a/icons/apex_app_chain_4689.gif b/icons/apex_app_chain_4689.gif new file mode 100644 index 000000000..3ab9ecc7c Binary files /dev/null and b/icons/apex_app_chain_4689.gif differ diff --git a/icons/apex_app_chain_50.gif b/icons/apex_app_chain_50.gif new file mode 100644 index 000000000..0bf2d4ef8 Binary files /dev/null and b/icons/apex_app_chain_50.gif differ diff --git a/icons/apex_app_chain_592.gif b/icons/apex_app_chain_592.gif new file mode 100644 index 000000000..8689c2efe Binary files /dev/null and b/icons/apex_app_chain_592.gif differ diff --git a/icons/apex_app_chain_60.gif b/icons/apex_app_chain_60.gif new file mode 100644 index 000000000..9eba09840 Binary files /dev/null and b/icons/apex_app_chain_60.gif differ diff --git a/icons/apex_app_chain_61.gif b/icons/apex_app_chain_61.gif new file mode 120000 index 000000000..2607a2eb0 --- /dev/null +++ b/icons/apex_app_chain_61.gif @@ -0,0 +1 @@ +apex_app_chain_1.gif \ No newline at end of file diff --git a/icons/apex_app_chain_64.gif b/icons/apex_app_chain_64.gif new file mode 100644 index 000000000..a5f394888 Binary files /dev/null and b/icons/apex_app_chain_64.gif differ diff --git a/icons/apex_app_chain_76.gif b/icons/apex_app_chain_76.gif new file mode 100644 index 000000000..6231b9b92 Binary files /dev/null and b/icons/apex_app_chain_76.gif differ diff --git a/icons/apex_app_chain_7762959.gif b/icons/apex_app_chain_7762959.gif new file mode 100644 index 000000000..3ceb7f602 Binary files /dev/null and b/icons/apex_app_chain_7762959.gif differ diff --git a/icons/apex_app_chain_78.gif b/icons/apex_app_chain_78.gif new file mode 100644 index 000000000..581424572 Binary files /dev/null and b/icons/apex_app_chain_78.gif differ diff --git a/icons/apex_app_chain_8.gif b/icons/apex_app_chain_8.gif new file mode 100644 index 000000000..261894a02 Binary files /dev/null and b/icons/apex_app_chain_8.gif differ diff --git a/icons/apex_app_chain_820.gif b/icons/apex_app_chain_820.gif new file mode 100644 index 000000000..7ab9ede0e Binary files /dev/null and b/icons/apex_app_chain_820.gif differ diff --git a/icons/apex_app_chain_846000.gif b/icons/apex_app_chain_846000.gif new file mode 100644 index 000000000..bc121cdbe Binary files /dev/null and b/icons/apex_app_chain_846000.gif differ diff --git a/icons/apex_app_chain_88.gif b/icons/apex_app_chain_88.gif new file mode 100644 index 000000000..76387e3ca Binary files /dev/null and b/icons/apex_app_chain_88.gif differ diff --git a/icons/apex_app_chain_888.gif b/icons/apex_app_chain_888.gif new file mode 100644 index 000000000..4dd970ac4 Binary files /dev/null and b/icons/apex_app_chain_888.gif differ diff --git a/icons/flex_app_chain_4689.gif b/icons/flex_app_chain_4689.gif index 807bcca0b..bf38c34c7 100644 Binary files a/icons/flex_app_chain_4689.gif and b/icons/flex_app_chain_4689.gif differ diff --git a/icons/nanox_app_chain_4689.gif b/icons/nanox_app_chain_4689.gif index 803797eed..935290a88 100644 Binary files a/icons/nanox_app_chain_4689.gif and b/icons/nanox_app_chain_4689.gif differ diff --git a/icons/stax_app_chain_4689.gif b/icons/stax_app_chain_4689.gif index de40f2c07..80bc8916f 100644 Binary files a/icons/stax_app_chain_4689.gif and b/icons/stax_app_chain_4689.gif differ diff --git a/ledger_app.toml b/ledger_app.toml index be129cb52..d32cc3309 100644 --- a/ledger_app.toml +++ b/ledger_app.toml @@ -1,10 +1,11 @@ [app] build_directory = "./" sdk = "C" -devices = ["nanox", "nanos+", "stax", "flex"] +devices = ["apex_p", "nanox", "nanos+", "stax", "flex"] [use_cases] whitelist_keys = "EIP7702_TEST_WHITELIST=1" +dbg_whitelist_keys = "DEBUG=1 EIP7702_TEST_WHITELIST=1" use_test_keys = "CAL_TEST_KEY=1 TRUSTED_NAME_TEST_KEY=1 SET_PLUGIN_TEST_KEY=1 NFT_TEST_KEY=1 EIP7702_TEST_WHITELIST=1" dbg_use_test_keys = "DEBUG=1 CAL_TEST_KEY=1 TRUSTED_NAME_TEST_KEY=1 SET_PLUGIN_TEST_KEY=1 NFT_TEST_KEY=1 EIP7702_TEST_WHITELIST=1" cal_bypass = "BYPASS_SIGNATURES=1" diff --git a/makefile_conf/features.mk b/makefile_conf/features.mk index 902b03197..4fd875873 100644 --- a/makefile_conf/features.mk +++ b/makefile_conf/features.mk @@ -43,10 +43,15 @@ endif # Transaction Checks # TODO: remove this check once the Transaction checks are implemented on all targets -ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX)) +ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX TARGET_APEX_M TARGET_APEX_P)) DEFINES += HAVE_TRANSACTION_CHECKS endif +# Safe Account +ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX TARGET_APEX_M TARGET_APEX_P)) + DEFINES += HAVE_SAFE_ACCOUNT +endif + EIP7702_TEST_WHITELIST ?= 0 ifneq ($(EIP7702_TEST_WHITELIST),0) DEFINES += HAVE_EIP7702_WHITELIST_TEST diff --git a/src/apdu_constants.h b/src/apdu_constants.h index 840e5e9f3..d97a09f9d 100644 --- a/src/apdu_constants.h +++ b/src/apdu_constants.h @@ -33,6 +33,7 @@ #define INS_PROVIDE_NETWORK_CONFIGURATION 0x30 #define INS_PROVIDE_TX_SIMULATION 0x32 #define INS_SIGN_EIP7702_AUTHORIZATION 0x34 +#define INS_PROVIDE_SAFE_ACCOUNT 0x36 #define INS_STR(x) \ (x == INS_GET_PUBLIC_KEY ? "GET_PUBLIC_KEY" \ @@ -59,6 +60,7 @@ : x == INS_PROVIDE_NETWORK_CONFIGURATION ? "PROVIDE_NETWORK_CONFIG" \ : x == INS_PROVIDE_TX_SIMULATION ? "PROVIDE_TX_SIMULATION" \ : x == INS_SIGN_EIP7702_AUTHORIZATION ? "SIGN_EIP7702_AUTHORIZATION" \ + : x == INS_PROVIDE_SAFE_ACCOUNT ? "PROVIDE_SAFE_ACCOUNT" \ : "Unknown") #define P1_CONFIRM 0x01 #define P1_NON_CONFIRM 0x00 @@ -84,6 +86,7 @@ #define APDU_RESPONSE_INVALID_DATA 0x6a80 #define APDU_RESPONSE_INSUFFICIENT_MEMORY 0x6a84 #define APDU_RESPONSE_REF_DATA_NOT_FOUND 0x6a88 +#define APDU_RESPONSE_FILE_ALREADY_EXIST 0x6a89 #define APDU_RESPONSE_INVALID_P1_P2 0x6b00 #define APDU_RESPONSE_INVALID_INS 0x6d00 #define APDU_RESPONSE_INVALID_CLA 0x6e00 @@ -140,4 +143,10 @@ uint16_t handleGetEth2PublicKey(uint8_t p1, #endif +uint16_t handle_safe_account(uint8_t p1, + uint8_t p2, + const uint8_t *data, + uint8_t length, + uint32_t *flags); + extern uint16_t apdu_response_code; diff --git a/src/common_ui.h b/src/common_ui.h index 5c137678b..4749d04ed 100644 --- a/src/common_ui.h +++ b/src/common_ui.h @@ -2,6 +2,7 @@ #include #include +#include "ui_logic.h" void ui_idle(void); void ui_error_blind_signing(void); @@ -9,18 +10,16 @@ void ui_display_public_eth2(void); void ui_display_privacy_public_key(void); void ui_display_privacy_shared_secret(void); void ui_display_public_key(const uint64_t *chain_id); -void ui_sign_712_v0(void); void ui_confirm_selector(void); void ui_confirm_parameter(void); +void ui_display_safe_account(void); // EIP-191 void ui_191_start(const char *message); // EIP-712 -void ui_712_start(void); -void ui_712_start_unfiltered(void); -void ui_712_switch_to_message(void); -void ui_712_switch_to_sign(void); +void ui_sign_712(void); +void ui_sign_712_v0(void); // Generic clear-signing bool ui_gcs(void); diff --git a/src/ledger_pki.c b/src/ledger_pki.c index 0d36218a1..7d1f10179 100644 --- a/src/ledger_pki.c +++ b/src/ledger_pki.c @@ -14,6 +14,7 @@ : x == CERTIFICATE_PUBLIC_KEY_USAGE_TX_SIMU_SIGNER ? "TX_SIMU_SIGNER" \ : x == CERTIFICATE_PUBLIC_KEY_USAGE_CALLDATA ? "CALLDATA" \ : x == CERTIFICATE_PUBLIC_KEY_USAGE_NETWORK ? "NETWORK" \ + : x == CERTIFICATE_PUBLIC_KEY_USAGE_LES_MULTISIG ? "SAFE" \ : "Unknown") int check_signature_with_pubkey(const char *tag, @@ -32,10 +33,7 @@ int check_signature_with_pubkey(const char *tag, uint8_t trusted_name[CERTIFICATE_TRUSTED_NAME_MAXLEN] = {0}; cx_ecfp_384_public_key_t public_key = {0}; - PRINTF( - "[%s] " - "=======================================================================================\n", - tag); + PRINTF("[%s] ==================================================================\n", tag); error = os_pki_get_info(&key_usage, trusted_name, &trusted_name_len, &public_key); if ((error == 0) && (key_usage == keyUsageExp)) { PRINTF("[%s] Certificate '%s' loaded for usage 0x%x (%s)\n", diff --git a/src/main.c b/src/main.c index 8cdfa9f86..31de83cdd 100644 --- a/src/main.c +++ b/src/main.c @@ -47,6 +47,8 @@ #include "sign_message.h" #include "ui_utils.h" #include "network_info.h" +#include "cmd_safe_account.h" +#include "tx_ctx.h" tmpCtx_t tmpCtx; txContext_t txContext; @@ -89,6 +91,9 @@ void reset_app_context(void) { } memset((uint8_t *) &txContext, 0, sizeof(txContext)); memset((uint8_t *) &tmpContent, 0, sizeof(tmpContent)); +#ifdef HAVE_SAFE_ACCOUNT + clear_safe_account(); +#endif ui_all_cleanup(); } @@ -261,6 +266,12 @@ static uint16_t handleApdu(command_t *cmd, uint32_t *flags, uint32_t *tx) { sw = handleSignEIP7702Authorization(cmd->p1, cmd->data, cmd->lc, flags); break; +#ifdef HAVE_SAFE_ACCOUNT + case INS_PROVIDE_SAFE_ACCOUNT: + sw = handle_safe_account(cmd->p1, cmd->p2, cmd->data, cmd->lc, flags); + break; +#endif + default: sw = APDU_RESPONSE_INVALID_INS; break; diff --git a/src/mem.c b/src/mem.c index 5e90e4439..cf56f8fe4 100644 --- a/src/mem.c +++ b/src/mem.c @@ -31,14 +31,19 @@ bool app_mem_init(void) { return mem_ctx != NULL; } -void *app_mem_alloc_impl(size_t size, const char *file, int line) { +void *app_mem_alloc_impl(size_t size, bool persistent, const char *file, int line) { void *ptr; ptr = mem_alloc(mem_ctx, size); #ifdef HAVE_MEMORY_PROFILING - PRINTF(MP_LOG_PREFIX "alloc;%u;0x%p;%s:%u\n", size, ptr, file, line); + if (persistent) { + PRINTF(MP_LOG_PREFIX "persist;%u;0x%p;%s:%u\n", size, ptr, file, line); + } else { + PRINTF(MP_LOG_PREFIX "alloc;%u;0x%p;%s:%u\n", size, ptr, file, line); + } #else (void) file; (void) line; + (void) persistent; #endif return ptr; } diff --git a/src/mem.h b/src/mem.h index 4013c86f7..305ac08b7 100644 --- a/src/mem.h +++ b/src/mem.h @@ -11,9 +11,9 @@ #define MP_FILE NULL #define MP_LINE 0 #endif -#define app_mem_alloc(size) app_mem_alloc_impl(size, MP_FILE, MP_LINE) +#define app_mem_alloc(size) app_mem_alloc_impl(size, false, MP_FILE, MP_LINE) #define app_mem_free(ptr) app_mem_free_impl(ptr, MP_FILE, MP_LINE) bool app_mem_init(void); -void *app_mem_alloc_impl(size_t size, const char *file, int line); +void *app_mem_alloc_impl(size_t size, bool persistent, const char *file, int line); void app_mem_free_impl(void *ptr, const char *file, int line); diff --git a/src/mem_utils.c b/src/mem_utils.c index 7321273b5..d81194fd8 100644 --- a/src/mem_utils.c +++ b/src/mem_utils.c @@ -11,7 +11,7 @@ * @param[in] value Value to write in memory * @return pointer to memory area or \ref NULL if the allocation failed */ -const char *mem_alloc_and_format_uint(uint32_t value) { +const char *mem_alloc_and_format_uint_impl(uint32_t value, const char *file, int line) { char *mem_ptr; uint32_t value_copy; uint8_t size; @@ -23,17 +23,17 @@ const char *mem_alloc_and_format_uint(uint32_t value) { size += 1; } // +1 for the null character - if ((mem_ptr = app_mem_alloc(sizeof(char) * (size + 1)))) { + if ((mem_ptr = app_mem_alloc_impl(sizeof(char) * (size + 1), false, file, line))) { snprintf(mem_ptr, (size + 1), "%u", value); } return mem_ptr; } -char *app_mem_strdup(const char *src) { +char *app_mem_strdup_impl(const char *src, const char *file, int line) { char *dst; size_t length = strlen(src) + 1; - if ((dst = app_mem_alloc(length)) != NULL) { + if ((dst = app_mem_alloc_impl(length, false, file, line)) != NULL) { memcpy(dst, src, length); } return dst; @@ -44,17 +44,22 @@ char *app_mem_strdup(const char *src) { * * @param[out] buffer Pointer to the buffer to allocate * @param[in] size Size of the buffer to allocate + * @param[in] persistent Whether the buffer should be persistent * @return true if the allocation was successful, false otherwise */ -bool mem_buffer_allocate(void **buffer, uint16_t size) { +bool mem_buffer_allocate_impl(void **buffer, + uint16_t size, + bool persistent, + const char *file, + int line) { if (size != 0) { // Check if the buffer is already allocated if (*buffer != NULL) { PRINTF("Buffer already allocated, freeing it before reallocating\n"); - app_mem_free(*buffer); + app_mem_free_impl(*buffer, file, line); } // Allocate the Title message buffer - if ((*buffer = app_mem_alloc(size)) == NULL) { + if ((*buffer = app_mem_alloc_impl(size, persistent, file, line)) == NULL) { PRINTF("Memory allocation failed for buffer of size %u\n", size); return false; } @@ -68,9 +73,9 @@ bool mem_buffer_allocate(void **buffer, uint16_t size) { * * @param[in] buffer Pointer to the buffer to deallocate */ -void mem_buffer_cleanup(void **buffer) { +void mem_buffer_cleanup_impl(void **buffer, const char *file, int line) { if (*buffer != NULL) { - app_mem_free(*buffer); + app_mem_free_impl(*buffer, file, line); *buffer = NULL; } } diff --git a/src/mem_utils.h b/src/mem_utils.h index 2e2c4e1f5..e1b0e1b7f 100644 --- a/src/mem_utils.h +++ b/src/mem_utils.h @@ -1,9 +1,27 @@ #pragma once +#include #include -const char *mem_alloc_and_format_uint(uint32_t value); -char *app_mem_strdup(const char *s); +#ifdef HAVE_MEMORY_PROFILING +#define MP_FILE __FILE__ +#define MP_LINE __LINE__ +#else +#define MP_FILE NULL +#define MP_LINE 0 +#endif +#define mem_buffer_allocate(ptr, size) mem_buffer_allocate_impl(ptr, size, false, MP_FILE, MP_LINE) +#define mem_buffer_persistent(ptr, size) mem_buffer_allocate_impl(ptr, size, true, MP_FILE, MP_LINE) +#define mem_buffer_cleanup(ptr) mem_buffer_cleanup_impl(ptr, MP_FILE, MP_LINE) +#define mem_alloc_and_format_uint(value) mem_alloc_and_format_uint_impl(value, MP_FILE, MP_LINE) +#define app_mem_strdup(ptr) app_mem_strdup_impl(ptr, MP_FILE, MP_LINE) -bool mem_buffer_allocate(void **buffer, uint16_t size); -void mem_buffer_cleanup(void **buffer); +const char *mem_alloc_and_format_uint_impl(uint32_t value, const char *file, int line); +char *app_mem_strdup_impl(const char *s, const char *file, int line); + +bool mem_buffer_allocate_impl(void **buffer, + uint16_t size, + bool persistent, + const char *file, + int line); +void mem_buffer_cleanup_impl(void **buffer, const char *file, int line); diff --git a/src/shared_context.h b/src/shared_context.h index afa3eb3ba..f1ad92181 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -132,11 +132,9 @@ typedef struct txStringProperties_s { } txStringProperties_t; #define SHARED_CTX_FIELD_1_SIZE 380 -#define SHARED_CTX_FIELD_2_SIZE 40 typedef struct strDataTmp_s { char tmp[SHARED_CTX_FIELD_1_SIZE]; - char tmp2[SHARED_CTX_FIELD_2_SIZE]; } strDataTmp_t; typedef union { diff --git a/src_features/generic_tx_parser/calldata.c b/src_features/generic_tx_parser/calldata.c index 2a690373b..127687ce5 100644 --- a/src_features/generic_tx_parser/calldata.c +++ b/src_features/generic_tx_parser/calldata.c @@ -6,40 +6,23 @@ #include "mem_utils.h" #include "list.h" -typedef enum { - CHUNK_STRIP_LEFT = 0, - CHUNK_STRIP_RIGHT = 1, -} e_chunk_strip_dir; +s_calldata *calldata_init(size_t size, const uint8_t selector[CALLDATA_SELECTOR_SIZE]) { + s_calldata *calldata; -typedef struct { - s_flist_node _list; - e_chunk_strip_dir dir : 1; - uint8_t size : 7; - uint8_t *buf; -} s_calldata_chunk; - -typedef struct { - size_t expected_size; - size_t received_size; - - uint8_t selector[CALLDATA_SELECTOR_SIZE]; - s_calldata_chunk *chunks; - - uint8_t chunk[CALLDATA_CHUNK_SIZE]; - size_t chunk_size; -} s_calldata; - -static s_calldata *g_calldata = NULL; - -bool calldata_init(size_t size) { - if (g_calldata != NULL) { - calldata_cleanup(); + if ((calldata = app_mem_alloc(sizeof(*calldata))) == NULL) { + return NULL; } - if ((g_calldata = app_mem_alloc(sizeof(*g_calldata))) == NULL) { + explicit_bzero(calldata, sizeof(*calldata)); + calldata->expected_size = size; + calldata_set_selector(calldata, selector); + return calldata; +} + +bool calldata_set_selector(s_calldata *calldata, const uint8_t selector[CALLDATA_SELECTOR_SIZE]) { + if ((calldata == NULL) || (selector == NULL)) { return false; } - explicit_bzero(g_calldata, sizeof(*g_calldata)); - g_calldata->expected_size = size; + memcpy(calldata->selector, selector, sizeof(calldata->selector)); return true; } @@ -106,63 +89,48 @@ static bool decompress_chunk(const s_calldata_chunk *chunk, uint8_t *out) { return true; } -bool calldata_append(const uint8_t *buffer, size_t size) { +bool calldata_append(s_calldata *calldata, const uint8_t *buffer, size_t size) { uint8_t cpy_length; - if (g_calldata == NULL) return false; - if ((g_calldata->received_size + size) > g_calldata->expected_size) { - calldata_cleanup(); + if (calldata == NULL) return false; + if ((calldata->received_size + size) > calldata->expected_size) { return false; } - // selector handling - if (g_calldata->chunks == NULL) { - if (size < CALLDATA_SELECTOR_SIZE) { - // somehow getting an incomplete selector - calldata_cleanup(); - return false; - } - memcpy(g_calldata->selector, buffer, CALLDATA_SELECTOR_SIZE); - buffer += CALLDATA_SELECTOR_SIZE; - size -= CALLDATA_SELECTOR_SIZE; - g_calldata->received_size += CALLDATA_SELECTOR_SIZE; - } - // chunk handling while (size > 0) { - if (g_calldata->received_size > g_calldata->expected_size) { - calldata_cleanup(); + if (calldata->received_size > calldata->expected_size) { return false; } - cpy_length = MIN(size, (sizeof(g_calldata->chunk) - g_calldata->chunk_size)); - memcpy(&g_calldata->chunk[g_calldata->chunk_size], buffer, cpy_length); - g_calldata->chunk_size += cpy_length; - if (g_calldata->chunk_size == CALLDATA_CHUNK_SIZE) { - if (!compress_chunk(g_calldata)) { - calldata_cleanup(); + cpy_length = MIN(size, (sizeof(calldata->chunk) - calldata->chunk_size)); + memcpy(&calldata->chunk[calldata->chunk_size], buffer, cpy_length); + calldata->chunk_size += cpy_length; + if (calldata->chunk_size == CALLDATA_CHUNK_SIZE) { + if (!compress_chunk(calldata)) { return false; } - g_calldata->chunk_size = 0; + calldata->chunk_size = 0; } buffer += cpy_length; size -= cpy_length; - g_calldata->received_size += cpy_length; + calldata->received_size += cpy_length; } - if (g_calldata->received_size == g_calldata->expected_size) { #ifdef HAVE_PRINTF + if (calldata->received_size == calldata->expected_size) { // get allocated size - size_t compressed_size = sizeof(*g_calldata); - for (s_calldata_chunk *chunk = g_calldata->chunks; chunk != NULL; + size_t compressed_size = sizeof(*calldata); + for (s_calldata_chunk *chunk = calldata->chunks; chunk != NULL; chunk = (s_calldata_chunk *) ((s_flist_node *) chunk)->next) { compressed_size += sizeof(*chunk); compressed_size += chunk->size; } PRINTF("calldata size went from %u to %u bytes with compression\n", - g_calldata->received_size, + calldata->received_size, compressed_size); -#endif + calldata_dump(calldata); } +#endif return true; } @@ -174,13 +142,9 @@ static void delete_calldata_chunk(s_calldata_chunk *node) { app_mem_free(node); } -void calldata_cleanup(void) { - if (g_calldata != NULL) { - flist_clear((s_flist_node **) &g_calldata->chunks, - (f_list_node_del) &delete_calldata_chunk); - app_mem_free(g_calldata); - g_calldata = NULL; - } +void calldata_delete(s_calldata *node) { + flist_clear((s_flist_node **) &node->chunks, (f_list_node_del) &delete_calldata_chunk); + app_mem_free(node); } static bool has_valid_calldata(const s_calldata *calldata) { @@ -195,24 +159,42 @@ static bool has_valid_calldata(const s_calldata *calldata) { return true; } -const uint8_t *calldata_get_selector(void) { - if (!has_valid_calldata(g_calldata)) { +const uint8_t *calldata_get_selector(const s_calldata *calldata) { + if (!has_valid_calldata(calldata)) { return NULL; } - return g_calldata->selector; + return calldata->selector; } -const uint8_t *calldata_get_chunk(int idx) { +const uint8_t *calldata_get_chunk(s_calldata *calldata, int idx) { s_calldata_chunk *chunk; - if (!has_valid_calldata(g_calldata) || (g_calldata->chunks == NULL)) { + if (!has_valid_calldata(calldata) || (calldata->chunks == NULL)) { return NULL; } - chunk = g_calldata->chunks; + chunk = calldata->chunks; for (int i = 0; i < idx; ++i) { if (((s_flist_node *) chunk)->next == NULL) return NULL; chunk = (s_calldata_chunk *) ((s_flist_node *) chunk)->next; } - if (!decompress_chunk(chunk, g_calldata->chunk)) return NULL; - return g_calldata->chunk; + if (!decompress_chunk(chunk, calldata->chunk)) return NULL; + return calldata->chunk; +} + +void calldata_dump(const s_calldata *calldata) { +#ifdef HAVE_PRINTF + int i = 0; + uint8_t buf[CALLDATA_CHUNK_SIZE]; + + PRINTF("=== calldata at 0x%p ===\n", calldata); + PRINTF("selector = 0x%.*h\n", sizeof(calldata->selector), calldata->selector); + for (s_calldata_chunk *chunk = calldata->chunks; chunk != NULL; + chunk = (s_calldata_chunk *) ((s_flist_node *) chunk)->next) { + if (!decompress_chunk(chunk, buf)) break; + PRINTF("[%02u] %.*h\n", i++, CALLDATA_CHUNK_SIZE, buf); + } + PRINTF("========================\n"); +#else + (void) calldata; +#endif } diff --git a/src_features/generic_tx_parser/calldata.h b/src_features/generic_tx_parser/calldata.h index c694d5a5c..82b85e5d4 100644 --- a/src_features/generic_tx_parser/calldata.h +++ b/src_features/generic_tx_parser/calldata.h @@ -3,12 +3,38 @@ #include #include #include +#include "list.h" #define CALLDATA_SELECTOR_SIZE 4 #define CALLDATA_CHUNK_SIZE 32 -bool calldata_init(size_t size); -bool calldata_append(const uint8_t *buffer, size_t size); -void calldata_cleanup(void); -const uint8_t *calldata_get_selector(void); -const uint8_t *calldata_get_chunk(int idx); +typedef enum { + CHUNK_STRIP_LEFT = 0, + CHUNK_STRIP_RIGHT = 1, +} e_chunk_strip_dir; + +typedef struct { + s_flist_node _list; + e_chunk_strip_dir dir : 1; + uint8_t size : 7; + uint8_t *buf; +} s_calldata_chunk; + +typedef struct { + size_t expected_size; + size_t received_size; + + uint8_t selector[CALLDATA_SELECTOR_SIZE]; + s_calldata_chunk *chunks; + + uint8_t chunk[CALLDATA_CHUNK_SIZE]; + size_t chunk_size; +} s_calldata; + +s_calldata *calldata_init(size_t size, const uint8_t selector[CALLDATA_SELECTOR_SIZE]); +bool calldata_set_selector(s_calldata *calldata, const uint8_t selector[CALLDATA_SELECTOR_SIZE]); +bool calldata_append(s_calldata *calldata, const uint8_t *buffer, size_t size); +void calldata_delete(s_calldata *node); +const uint8_t *calldata_get_selector(const s_calldata *calldata); +const uint8_t *calldata_get_chunk(s_calldata *calldata, int idx); +void calldata_dump(const s_calldata *calldata); diff --git a/src_features/generic_tx_parser/cmd_field.c b/src_features/generic_tx_parser/cmd_field.c index 90208ea0c..c414df79f 100644 --- a/src_features/generic_tx_parser/cmd_field.c +++ b/src_features/generic_tx_parser/cmd_field.c @@ -6,6 +6,7 @@ #include "gtp_field.h" #include "cmd_tx_info.h" #include "gtp_tx_info.h" +#include "tx_ctx.h" static bool handle_tlv_payload(const uint8_t *payload, uint16_t size) { s_field field = {0}; @@ -22,20 +23,23 @@ static bool handle_tlv_payload(const uint8_t *payload, uint16_t size) { return false; } if (!format_field(&field)) { - PRINTF("Error while formatting the field\n"); return false; } + while (((appState == APP_STATE_SIGNING_EIP712) || !tx_ctx_is_root()) && + validate_instruction_hash()) { + tx_ctx_pop(); + } return true; } uint16_t handle_field(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *payload) { (void) p2; - if (appState != APP_STATE_SIGNING_TX) { + if ((appState != APP_STATE_SIGNING_TX) && (appState != APP_STATE_SIGNING_EIP712)) { PRINTF("App not in TX signing mode!\n"); return APDU_RESPONSE_CONDITION_NOT_SATISFIED; } - if (g_tx_info == NULL) { + if (get_current_tx_info() == NULL) { PRINTF("Error: Field received without a TX info!\n"); gcs_cleanup(); return APDU_RESPONSE_CONDITION_NOT_SATISFIED; diff --git a/src_features/generic_tx_parser/cmd_tx_info.c b/src_features/generic_tx_parser/cmd_tx_info.c index 816796d74..aba19a185 100644 --- a/src_features/generic_tx_parser/cmd_tx_info.c +++ b/src_features/generic_tx_parser/cmd_tx_info.c @@ -6,59 +6,37 @@ #include "gtp_tx_info.h" #include "tlv.h" #include "tlv_apdu.h" -#include "calldata.h" -#include "gtp_field_table.h" -#include "common_ui.h" -#include "ui_utils.h" -#include "mem_utils.h" +#include "tx_ctx.h" static bool handle_tlv_payload(const uint8_t *payload, uint16_t size) { s_tx_info_ctx ctx = {0}; bool parsing_ret; - ctx.tx_info = g_tx_info; + if ((ctx.tx_info = app_mem_alloc(sizeof(*ctx.tx_info))) == NULL) { + return false; + } explicit_bzero(ctx.tx_info, sizeof(*ctx.tx_info)); - cx_sha256_init((cx_sha256_t *) &ctx.struct_hash); + cx_sha256_init(&ctx.struct_hash); parsing_ret = tlv_parse(payload, size, (f_tlv_data_handler) &handle_tx_info_struct, &ctx); if (!parsing_ret || !verify_tx_info_struct(&ctx)) { return false; } - if (cx_sha3_init_no_throw(&ctx.tx_info->fields_hash_ctx, 256) != CX_OK) { + if (!find_matching_tx_ctx(ctx.tx_info->contract_addr, + ctx.tx_info->selector, + &ctx.tx_info->chain_id)) { return false; } - return field_table_init(); + return set_tx_info_into_tx_ctx(ctx.tx_info); } uint16_t handle_tx_info(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *payload) { (void) p2; - if (appState != APP_STATE_SIGNING_TX) { + if ((appState != APP_STATE_SIGNING_TX) && (appState != APP_STATE_SIGNING_EIP712)) { PRINTF("App not in TX signing mode!\n"); return APDU_RESPONSE_CONDITION_NOT_SATISFIED; } - - if (p1 == P1_FIRST_CHUNK) { - if (g_tx_info != NULL) { - PRINTF("Error: TX info received when one was still in RAM!\n"); - gcs_cleanup(); - return APDU_RESPONSE_CONDITION_NOT_SATISFIED; - } - - if ((g_tx_info = app_mem_alloc(sizeof(*g_tx_info))) == NULL) { - return APDU_RESPONSE_INSUFFICIENT_MEMORY; - } - } - if (g_tx_info == NULL) { - return APDU_RESPONSE_INVALID_DATA; - } if (!tlv_from_apdu(p1 == P1_FIRST_CHUNK, lc, payload, &handle_tlv_payload)) { return APDU_RESPONSE_INVALID_DATA; } return APDU_RESPONSE_OK; } - -void gcs_cleanup(void) { - ui_gcs_cleanup(); - field_table_cleanup(); - mem_buffer_cleanup((void **) &g_tx_info); - calldata_cleanup(); -} diff --git a/src_features/generic_tx_parser/cmd_tx_info.h b/src_features/generic_tx_parser/cmd_tx_info.h index 5f207e2aa..48e6b80c4 100644 --- a/src_features/generic_tx_parser/cmd_tx_info.h +++ b/src_features/generic_tx_parser/cmd_tx_info.h @@ -1,7 +1,5 @@ #pragma once #include -#include "gtp_tx_info.h" uint16_t handle_tx_info(uint8_t p1, uint8_t p2, uint8_t lc, const uint8_t *payload); -void gcs_cleanup(void); diff --git a/src_features/generic_tx_parser/gtp_data_path.c b/src_features/generic_tx_parser/gtp_data_path.c index 7cf1d07e1..673399adf 100644 --- a/src_features/generic_tx_parser/gtp_data_path.c +++ b/src_features/generic_tx_parser/gtp_data_path.c @@ -6,6 +6,7 @@ #include "utils.h" #include "calldata.h" #include "mem.h" +#include "tx_ctx.h" enum { TAG_VERSION = 0x00, @@ -127,7 +128,7 @@ static bool path_ref(uint32_t *offset, uint32_t *ref_offset) { uint8_t buf[sizeof(uint16_t)]; const uint8_t *chunk; - if ((chunk = calldata_get_chunk(*offset)) == NULL) { + if ((chunk = calldata_get_chunk(get_current_calldata(), *offset)) == NULL) { return false; } buf_shrink_expand(chunk, CALLDATA_CHUNK_SIZE, buf, sizeof(buf)); @@ -154,7 +155,7 @@ static bool path_leaf(const s_leaf_args *leaf, break; case LEAF_TYPE_DYNAMIC: - if ((chunk = calldata_get_chunk(*offset)) == NULL) { + if ((chunk = calldata_get_chunk(get_current_calldata(), *offset)) == NULL) { return false; } buf_shrink_expand(chunk, CALLDATA_CHUNK_SIZE, buf, sizeof(buf)); @@ -174,7 +175,7 @@ static bool path_leaf(const s_leaf_args *leaf, for (int chunk_idx = 0; (chunk_idx * CALLDATA_CHUNK_SIZE) < collection->value[collection->size].length; ++chunk_idx) { - if ((chunk = calldata_get_chunk(*offset + chunk_idx)) == NULL) { + if ((chunk = calldata_get_chunk(get_current_calldata(), *offset + chunk_idx)) == NULL) { app_mem_free(leaf_buf); return false; } @@ -242,7 +243,7 @@ static bool path_array(const s_array_args *array, if (arrays_info->index >= MAX_ARRAYS) { return false; } - if ((chunk = calldata_get_chunk(*offset)) == NULL) { + if ((chunk = calldata_get_chunk(get_current_calldata(), *offset)) == NULL) { return false; } buf_shrink_expand(chunk, CALLDATA_CHUNK_SIZE, buf, sizeof(buf)); diff --git a/src_features/generic_tx_parser/gtp_field.c b/src_features/generic_tx_parser/gtp_field.c index de8e3da24..954b2e01e 100644 --- a/src_features/generic_tx_parser/gtp_field.c +++ b/src_features/generic_tx_parser/gtp_field.c @@ -2,6 +2,7 @@ #include "gtp_field.h" #include "utils.h" #include "os_print.h" +#include "shared_context.h" // strings enum { BIT_VERSION = 0, @@ -27,6 +28,7 @@ typedef union { s_param_unit_context unit_ctx; s_param_enum_context enum_ctx; s_param_trusted_name_context trusted_name_ctx; + s_param_calldata_context calldata_ctx; s_param_token_context token_ctx; } u_param_context; @@ -67,6 +69,7 @@ static bool handle_param_type(const s_tlv_data *data, s_field_ctx *context) { case PARAM_TYPE_UNIT: case PARAM_TYPE_ENUM: case PARAM_TYPE_TRUSTED_NAME: + case PARAM_TYPE_CALLDATA: case PARAM_TYPE_TOKEN: break; default: @@ -126,6 +129,10 @@ static bool handle_param(const s_tlv_data *data, s_field_ctx *context) { handler = (f_tlv_data_handler) &handle_param_trusted_name_struct; param_ctx.trusted_name_ctx.param = &context->field->param_trusted_name; break; + case PARAM_TYPE_CALLDATA: + handler = (f_tlv_data_handler) &handle_param_calldata_struct; + param_ctx.calldata_ctx.param = &context->field->param_calldata; + break; case PARAM_TYPE_TOKEN: handler = (f_tlv_data_handler) &handle_param_token_struct; param_ctx.token_ctx.param = &context->field->param_token; @@ -218,11 +225,16 @@ bool format_field(const s_field *field) { case PARAM_TYPE_TRUSTED_NAME: ret = format_param_trusted_name(&field->param_trusted_name, field->name); break; + case PARAM_TYPE_CALLDATA: + ret = format_param_calldata(&field->param_calldata, field->name); + break; case PARAM_TYPE_TOKEN: ret = format_param_token(&field->param_token, field->name); break; default: ret = false; } + // so that EIP-712 error-handling does trigger + strings.tmp.tmp[0] = '\0'; return ret; } diff --git a/src_features/generic_tx_parser/gtp_field.h b/src_features/generic_tx_parser/gtp_field.h index 4cabe1b6a..4af3d990a 100644 --- a/src_features/generic_tx_parser/gtp_field.h +++ b/src_features/generic_tx_parser/gtp_field.h @@ -12,7 +12,9 @@ #include "gtp_param_unit.h" #include "gtp_param_enum.h" #include "gtp_param_trusted_name.h" +#include "gtp_param_calldata.h" #include "gtp_param_token.h" +#include "list.h" typedef enum { PARAM_TYPE_RAW = 0, @@ -42,6 +44,7 @@ typedef struct { s_param_unit param_unit; s_param_enum param_enum; s_param_trusted_name param_trusted_name; + s_param_calldata param_calldata; s_param_token param_token; }; } s_field; diff --git a/src_features/generic_tx_parser/gtp_field_table.c b/src_features/generic_tx_parser/gtp_field_table.c index 3cb53520d..c125bef4a 100644 --- a/src_features/generic_tx_parser/gtp_field_table.c +++ b/src_features/generic_tx_parser/gtp_field_table.c @@ -3,6 +3,8 @@ #include "gtp_field_table.h" #include "mem.h" #include "list.h" +#include "shared_context.h" // appState +#include "ui_logic.h" typedef struct { s_flist_node _list; @@ -39,6 +41,11 @@ bool add_to_field_table(e_param_type type, const char *key, const char *value) { PRINTF("Error: NULL key/value!\n"); return false; } + if (appState == APP_STATE_SIGNING_EIP712) { + ui_712_set_title(key, strlen(key)); + ui_712_set_value(value, strlen(value)); + return true; + } if ((node = app_mem_alloc(sizeof(*node))) == NULL) { return false; } @@ -64,6 +71,10 @@ bool add_to_field_table(e_param_type type, const char *key, const char *value) { return true; } +bool set_intent_field(const char *value) { + return add_to_field_table(0, "Transaction type", value); +} + size_t field_table_size(void) { return flist_size((s_flist_node **) &g_table); } diff --git a/src_features/generic_tx_parser/gtp_field_table.h b/src_features/generic_tx_parser/gtp_field_table.h index b49d44a98..1f7ffcf7a 100644 --- a/src_features/generic_tx_parser/gtp_field_table.h +++ b/src_features/generic_tx_parser/gtp_field_table.h @@ -13,5 +13,6 @@ typedef struct { bool field_table_init(void); void field_table_cleanup(void); bool add_to_field_table(e_param_type type, const char *key, const char *value); +bool set_intent_field(const char *value); size_t field_table_size(void); const s_field_table_entry *get_from_field_table(int index); diff --git a/src_features/generic_tx_parser/gtp_param_amount.c b/src_features/generic_tx_parser/gtp_param_amount.c index 310572ce1..3d7a249ed 100644 --- a/src_features/generic_tx_parser/gtp_param_amount.c +++ b/src_features/generic_tx_parser/gtp_param_amount.c @@ -3,6 +3,7 @@ #include "common_utils.h" #include "gtp_field_table.h" #include "shared_context.h" +#include "tx_ctx.h" enum { TAG_VERSION = 0x00, @@ -51,7 +52,8 @@ bool format_param_amount(const s_param_amount *param, const char *name) { size_t buf_size = sizeof(strings.tmp.tmp); if ((ret = value_get(¶m->value, &collec))) { - chain_id = get_tx_chain_id(); + if (get_current_tx_info() == NULL) return false; + chain_id = get_current_tx_info()->chain_id; ticker = get_displayable_ticker(&chain_id, chainConfig); for (int i = 0; i < collec.size; ++i) { if (!(ret = amountToString(collec.value[i].ptr, diff --git a/src_features/generic_tx_parser/gtp_param_calldata.c b/src_features/generic_tx_parser/gtp_param_calldata.c new file mode 100644 index 000000000..86bdabed4 --- /dev/null +++ b/src_features/generic_tx_parser/gtp_param_calldata.c @@ -0,0 +1,265 @@ +#include "gtp_param_calldata.h" +#include "network.h" +#include "common_utils.h" +#include "gtp_field_table.h" +#include "shared_context.h" +#include "gtp_tx_info.h" +#include "utils.h" +#include "read.h" +#include "tx_ctx.h" + +enum { + TAG_VERSION = 0x00, + TAG_VALUE = 0x01, + TAG_CALLEE = 0x02, + TAG_CHAIN_ID = 0x03, + TAG_SELECTOR = 0x04, + TAG_AMOUNT = 0x05, + TAG_SPENDER = 0x06, +}; + +static bool handle_version(const s_tlv_data *data, s_param_calldata_context *context) { + if (data->length != sizeof(context->param->version)) { + return false; + } + context->param->version = data->value[0]; + return true; +} + +static bool handle_value(const s_tlv_data *data, s_param_calldata_context *context) { + s_value_context ctx = {0}; + + ctx.value = &context->param->calldata; + explicit_bzero(ctx.value, sizeof(*ctx.value)); + return tlv_parse(data->value, data->length, (f_tlv_data_handler) &handle_value_struct, &ctx); +} + +static bool handle_callee(const s_tlv_data *data, s_param_calldata_context *context) { + s_value_context ctx = {0}; + + ctx.value = &context->param->contract_addr; + explicit_bzero(ctx.value, sizeof(*ctx.value)); + return tlv_parse(data->value, data->length, (f_tlv_data_handler) &handle_value_struct, &ctx); +} + +static bool handle_chain_id(const s_tlv_data *data, s_param_calldata_context *context) { + s_value_context ctx = {0}; + + ctx.value = &context->param->chain_id; + explicit_bzero(ctx.value, sizeof(*ctx.value)); + context->param->has_chain_id = true; + return tlv_parse(data->value, data->length, (f_tlv_data_handler) &handle_value_struct, &ctx); +} + +static bool handle_selector(const s_tlv_data *data, s_param_calldata_context *context) { + s_value_context ctx = {0}; + + ctx.value = &context->param->selector; + explicit_bzero(ctx.value, sizeof(*ctx.value)); + context->param->has_selector = true; + return tlv_parse(data->value, data->length, (f_tlv_data_handler) &handle_value_struct, &ctx); +} + +static bool handle_amount(const s_tlv_data *data, s_param_calldata_context *context) { + s_value_context ctx = {0}; + + ctx.value = &context->param->amount; + explicit_bzero(ctx.value, sizeof(*ctx.value)); + context->param->has_amount = true; + return tlv_parse(data->value, data->length, (f_tlv_data_handler) &handle_value_struct, &ctx); +} + +static bool handle_spender(const s_tlv_data *data, s_param_calldata_context *context) { + s_value_context ctx = {0}; + + ctx.value = &context->param->spender; + explicit_bzero(ctx.value, sizeof(*ctx.value)); + context->param->has_spender = true; + return tlv_parse(data->value, data->length, (f_tlv_data_handler) &handle_value_struct, &ctx); +} + +bool handle_param_calldata_struct(const s_tlv_data *data, s_param_calldata_context *context) { + bool ret; + + switch (data->tag) { + case TAG_VERSION: + ret = handle_version(data, context); + break; + case TAG_VALUE: + ret = handle_value(data, context); + break; + case TAG_CALLEE: + ret = handle_callee(data, context); + break; + case TAG_CHAIN_ID: + ret = handle_chain_id(data, context); + break; + case TAG_SELECTOR: + ret = handle_selector(data, context); + break; + case TAG_AMOUNT: + ret = handle_amount(data, context); + break; + case TAG_SPENDER: + ret = handle_spender(data, context); + break; + default: + PRINTF(TLV_TAG_ERROR_MSG, data->tag); + ret = false; + } + return ret; +} + +static bool process_nested_calldata(const s_param_calldata *param, + const s_parsed_value *calldata, + const s_parsed_value *contract_addr, + const s_parsed_value *chain_id, + const s_parsed_value *selector, + const s_parsed_value *amount, + const s_parsed_value *spender) { + uint8_t addr_buf[ADDRESS_LENGTH]; + uint8_t selector_buf[CALLDATA_SELECTOR_SIZE]; + const uint8_t *calldata_buf; + size_t calldata_length; + s_calldata *new_calldata; + uint8_t amount_buf[INT256_LENGTH]; + uint8_t from_buf[ADDRESS_LENGTH]; + uint64_t chain_id_value; + uint8_t chain_id_buf[sizeof(chain_id_value)]; + + if (param->has_chain_id) { + buf_shrink_expand(chain_id->ptr, chain_id->length, chain_id_buf, sizeof(chain_id_buf)); + chain_id_value = read_u64_be(chain_id_buf, 0); + } + + if (param->has_selector) { + buf_shrink_expand(selector->ptr, selector->length, selector_buf, sizeof(selector_buf)); + calldata_buf = calldata->ptr; + calldata_length = calldata->length; + } else { + if (calldata->length < CALLDATA_SELECTOR_SIZE) { + return false; + } + memcpy(selector_buf, calldata->ptr, CALLDATA_SELECTOR_SIZE); + calldata_buf = calldata->ptr + CALLDATA_SELECTOR_SIZE; + calldata_length = calldata->length - CALLDATA_SELECTOR_SIZE; + } + + buf_shrink_expand(contract_addr->ptr, contract_addr->length, addr_buf, sizeof(addr_buf)); + if (param->has_amount) { + buf_shrink_expand(amount->ptr, amount->length, amount_buf, sizeof(amount_buf)); + } + if (param->has_spender) { + buf_shrink_expand(spender->ptr, spender->length, from_buf, sizeof(from_buf)); + } + + if (((new_calldata = calldata_init(calldata_length, selector_buf)) == NULL) || + !calldata_append(new_calldata, calldata_buf, calldata_length)) { + return false; + } + if (!tx_ctx_init(new_calldata, + param->has_spender ? from_buf : NULL, + addr_buf, + param->has_amount ? amount_buf : NULL, + param->has_chain_id ? &chain_id_value : NULL)) { + calldata_delete(new_calldata); + return false; + } + return true; +} + +static bool process_fallback(const s_param_calldata *param, + const s_parsed_value *contract_addr, + const s_parsed_value *amount, + const s_parsed_value *spender) { + const char *ticker; + uint8_t decimals; + uint8_t addr[ADDRESS_LENGTH]; + char *buf = strings.tmp.tmp; + size_t buf_size = sizeof(strings.tmp.tmp); + + (void) spender; + if (param->has_amount && !allzeroes(amount->ptr, amount->length)) { + if (!set_intent_field("Send")) { + return false; + } + if (get_current_tx_info() == NULL) return false; + ticker = get_displayable_ticker(&get_current_tx_info()->chain_id, chainConfig); + decimals = WEI_TO_ETHER; + if (!amountToString(amount->ptr, amount->length, decimals, ticker, buf, buf_size)) { + return false; + } + if (!add_to_field_table(PARAM_TYPE_AMOUNT, "Amount", buf)) { + return false; + } + buf_shrink_expand(contract_addr->ptr, contract_addr->length, addr, sizeof(addr)); + if (!getEthDisplayableAddress(addr, buf, buf_size, chainConfig->chainId)) { + return false; + } + if (!add_to_field_table(PARAM_TYPE_RAW, "To", buf)) { + return false; + } + } + return true; +} + +bool format_param_calldata(const s_param_calldata *param, const char *name) { + bool ret = true; + s_parsed_value_collection calldatas = {0}; + s_parsed_value_collection contract_addrs = {0}; + s_parsed_value_collection chain_ids = {0}; + s_parsed_value_collection selectors = {0}; + s_parsed_value_collection amounts = {0}; + s_parsed_value_collection spenders = {0}; + + (void) name; + if ((ret = value_get(¶m->calldata, &calldatas))) { + if ((ret = value_get(¶m->contract_addr, &contract_addrs)) && + (contract_addrs.size == calldatas.size)) { + if ((!param->has_chain_id || ((ret = value_get(¶m->chain_id, &chain_ids)) && + (chain_ids.size == calldatas.size))) && + (!param->has_selector || ((ret = value_get(¶m->selector, &selectors)) && + (selectors.size == calldatas.size))) && + (!param->has_amount || ((ret = value_get(¶m->amount, &amounts)) && + (amounts.size == calldatas.size))) && + (!param->has_spender || ((ret = value_get(¶m->spender, &spenders)) && + (spenders.size == calldatas.size)))) { + for (int i = 0; i < calldatas.size; ++i) { + if (calldatas.value[i].length > 0) { + if (!process_nested_calldata(param, + &calldatas.value[i], + &contract_addrs.value[i], + &chain_ids.value[i], + &selectors.value[i], + &amounts.value[i], + &spenders.value[i])) { + ret = false; + break; + } + } else { + if (i > 0) { + // within a batch execution, if any TX other than the first one has en + // empty calldata we won't be able to properly diplay it in order + ret = false; + break; + } + if (!process_fallback(param, + &contract_addrs.value[i], + &amounts.value[i], + &spenders.value[i])) { + ret = false; + break; + } + } + } + } + } + } + value_cleanup(¶m->calldata, &calldatas); + value_cleanup(¶m->contract_addr, &contract_addrs); + value_cleanup(¶m->chain_id, &chain_ids); + value_cleanup(¶m->selector, &selectors); + value_cleanup(¶m->amount, &amounts); + value_cleanup(¶m->spender, &spenders); + return ret; +} diff --git a/src_features/generic_tx_parser/gtp_param_calldata.h b/src_features/generic_tx_parser/gtp_param_calldata.h new file mode 100644 index 000000000..05308eb8a --- /dev/null +++ b/src_features/generic_tx_parser/gtp_param_calldata.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include "tlv.h" +#include "gtp_value.h" + +typedef struct { + uint8_t version; + s_value calldata; + s_value contract_addr; + bool has_chain_id; + s_value chain_id; + bool has_selector; + s_value selector; + bool has_amount; + s_value amount; + bool has_spender; + s_value spender; +} s_param_calldata; + +typedef struct { + s_param_calldata *param; +} s_param_calldata_context; + +bool handle_param_calldata_struct(const s_tlv_data *data, s_param_calldata_context *context); +bool format_param_calldata(const s_param_calldata *param, const char *name); diff --git a/src_features/generic_tx_parser/gtp_param_enum.c b/src_features/generic_tx_parser/gtp_param_enum.c index 4cf5a3ee0..9ba3a78d5 100644 --- a/src_features/generic_tx_parser/gtp_param_enum.c +++ b/src_features/generic_tx_parser/gtp_param_enum.c @@ -4,6 +4,7 @@ #include "gtp_field_table.h" #include "calldata.h" #include "shared_context.h" +#include "tx_ctx.h" enum { TAG_VERSION = 0x00, @@ -64,14 +65,15 @@ bool format_param_enum(const s_param_enum *param, const char *name) { const uint8_t *selector; if ((ret = value_get(¶m->value, &collec))) { - chain_id = get_tx_chain_id(); + if (get_current_tx_info() == NULL) return false; + chain_id = get_current_tx_info()->chain_id; for (int i = 0; i < collec.size; ++i) { if (collec.value[i].length == 0) { ret = false; break; } value = collec.value[i].ptr[collec.value[i].length - 1]; - if ((selector = calldata_get_selector()) == NULL) { + if ((selector = calldata_get_selector(get_current_calldata())) == NULL) { ret = false; break; } diff --git a/src_features/generic_tx_parser/gtp_param_token.c b/src_features/generic_tx_parser/gtp_param_token.c index 5d241a50c..25fd312e2 100644 --- a/src_features/generic_tx_parser/gtp_param_token.c +++ b/src_features/generic_tx_parser/gtp_param_token.c @@ -5,6 +5,7 @@ #include "manage_asset_info.h" #include "network.h" #include "gtp_field_table.h" +#include "tx_ctx.h" enum { TAG_VERSION = 0x00, @@ -80,7 +81,8 @@ bool format_param_token(const s_param_token *param, const char *name) { uint64_t chain_id; const char *ticker = NULL; - chain_id = get_tx_chain_id(); + if (get_current_tx_info() == NULL) return false; + chain_id = get_current_tx_info()->chain_id; if ((ret = value_get(¶m->address, &collec))) { for (int i = 0; i < collec.size; ++i) { buf_shrink_expand(collec.value[i].ptr, collec.value[i].length, addr, sizeof(addr)); diff --git a/src_features/generic_tx_parser/gtp_param_token_amount.c b/src_features/generic_tx_parser/gtp_param_token_amount.c index af9e0f4ef..250cf884b 100644 --- a/src_features/generic_tx_parser/gtp_param_token_amount.c +++ b/src_features/generic_tx_parser/gtp_param_token_amount.c @@ -4,6 +4,7 @@ #include "utils.h" #include "gtp_field_table.h" #include "manage_asset_info.h" +#include "tx_ctx.h" enum { TAG_VERSION = 0x00, @@ -121,10 +122,12 @@ static bool process_token_amount(const s_param_token_amount *param, uint256_t zero256 = {0}; uint256_t val256; const tokenDefinition_t *token_def; - uint64_t chain_id = get_tx_chain_id(); + uint64_t chain_id; const char *ticker = g_unknown_ticker; uint8_t decimals = 0; + if (get_current_tx_info() == NULL) return false; + chain_id = get_current_tx_info()->chain_id; if (param->has_token) { buf_shrink_expand(token->ptr, token->length, addr_buf, sizeof(addr_buf)); if (match_native(addr_buf, param)) { diff --git a/src_features/generic_tx_parser/gtp_param_trusted_name.c b/src_features/generic_tx_parser/gtp_param_trusted_name.c index c1f3769c7..b7eb0e857 100644 --- a/src_features/generic_tx_parser/gtp_param_trusted_name.c +++ b/src_features/generic_tx_parser/gtp_param_trusted_name.c @@ -6,6 +6,7 @@ #include "shared_context.h" #include "getPublicKey.h" #include "apdu_constants.h" +#include "tx_ctx.h" enum { TAG_VERSION = 0x00, @@ -100,7 +101,8 @@ bool format_param_trusted_name(const s_param_trusted_name *param, const char *na e_param_type param_type; if ((ret = value_get(¶m->value, &values))) { - chain_id = get_tx_chain_id(); + if (get_current_tx_info() == NULL) return false; + chain_id = get_current_tx_info()->chain_id; for (int i = 0; i < values.size; ++i) { buf_shrink_expand(values.value[i].ptr, values.value[i].length, addr, sizeof(addr)); // replace by wallet addr if a match is found diff --git a/src_features/generic_tx_parser/gtp_tx_info.c b/src_features/generic_tx_parser/gtp_tx_info.c index 8bf60b466..66e02ed22 100644 --- a/src_features/generic_tx_parser/gtp_tx_info.c +++ b/src_features/generic_tx_parser/gtp_tx_info.c @@ -2,13 +2,13 @@ #include "gtp_tx_info.h" #include "read.h" #include "hash_bytes.h" -#include "network.h" // get_tx_chain_id -#include "shared_context.h" // txContext #include "utils.h" #include "time_format.h" #include "calldata.h" #include "public_keys.h" // LEDGER_SIGNATURE_PUBLIC_KEY #include "proxy_info.h" +#include "mem.h" +#include "tx_ctx.h" enum { BIT_VERSION = 0, @@ -40,8 +40,6 @@ enum { TAG_SIGNATURE = 0xff, }; -s_tx_info *g_tx_info = NULL; - static bool handle_version(const s_tlv_data *data, s_tx_info_ctx *context) { if (data->length != sizeof(context->tx_info->version)) { return false; @@ -60,10 +58,6 @@ static bool handle_chain_id(const s_tlv_data *data, s_tx_info_ctx *context) { } buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); chain_id = read_u64_be(buf, 0); - if (chain_id != get_tx_chain_id()) { - PRINTF("Error: chain ID mismatch!\n"); - return false; - } context->tx_info->chain_id = chain_id; context->set_flags |= SET_BIT(BIT_CHAIN_ID); return true; @@ -89,12 +83,14 @@ static bool handle_selector(const s_tlv_data *data, s_tx_info_ctx *context) { return false; } buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); - if ((selector = calldata_get_selector()) == NULL) { - return false; - } - if (memcmp(selector, buf, sizeof(buf)) != 0) { - PRINTF("Error: selector mismatch!\n"); - return false; + if (get_tx_ctx_count() == 0) { + if ((selector = calldata_get_selector(g_parked_calldata)) == NULL) { + return false; + } + if (memcmp(selector, buf, sizeof(buf)) != 0) { + PRINTF("Error: selector mismatch!\n"); + return false; + } } memcpy(context->tx_info->selector, buf, sizeof(buf)); context->set_flags |= SET_BIT(BIT_SELECTOR); @@ -239,8 +235,6 @@ bool handle_tx_info_struct(const s_tlv_data *data, s_tx_info_ctx *context) { bool verify_tx_info_struct(const s_tx_info_ctx *context) { uint16_t required_bits = 0; uint8_t hash[INT256_LENGTH]; - const uint8_t *proxy_parent; - uint64_t tx_chain_id; // check if struct version was provided required_bits |= SET_BIT(BIT_VERSION); @@ -266,19 +260,6 @@ bool verify_tx_info_struct(const s_tx_info_ctx *context) { return false; } - tx_chain_id = get_tx_chain_id(); - if (((proxy_parent = get_implem_contract(&tx_chain_id, - txContext.content->destination, - context->tx_info->selector)) == NULL) || - (memcmp(proxy_parent, context->tx_info->contract_addr, ADDRESS_LENGTH) != 0)) { - if (memcmp(context->tx_info->contract_addr, - txContext.content->destination, - ADDRESS_LENGTH) != 0) { - PRINTF("Error: contract address mismatch!\n"); - return false; - } - } - // verify signature if (cx_hash_no_throw((cx_hash_t *) &context->struct_hash, CX_LAST, @@ -303,67 +284,55 @@ bool verify_tx_info_struct(const s_tx_info_ctx *context) { return true; } -const char *get_operation_type(void) { - if (g_tx_info->operation_type[0] == '\0') { +const char *get_operation_type(const s_tx_info *tx_info) { + if ((tx_info == NULL) || (tx_info->operation_type[0] == '\0')) { return NULL; } - return g_tx_info->operation_type; + return tx_info->operation_type; } -const char *get_creator_name(void) { - if (g_tx_info->creator_name[0] == '\0') { +const char *get_creator_name(const s_tx_info *tx_info) { + if ((tx_info == NULL) || (tx_info->creator_name[0] == '\0')) { return NULL; } - return g_tx_info->creator_name; + return tx_info->creator_name; } -const char *get_creator_legal_name(void) { - if (g_tx_info->creator_legal_name[0] == '\0') { +const char *get_creator_legal_name(const s_tx_info *tx_info) { + if ((tx_info == NULL) || (tx_info->creator_legal_name[0] == '\0')) { return NULL; } - return g_tx_info->creator_legal_name; + return tx_info->creator_legal_name; } -const char *get_creator_url(void) { - if (g_tx_info->creator_url[0] == '\0') { +const char *get_creator_url(const s_tx_info *tx_info) { + if ((tx_info == NULL) || (tx_info->creator_url[0] == '\0')) { return NULL; } - return g_tx_info->creator_url; + return tx_info->creator_url; } -const char *get_contract_name(void) { - if (g_tx_info->contract_name[0] == '\0') { +const char *get_contract_name(const s_tx_info *tx_info) { + if ((tx_info == NULL) || (tx_info->contract_name[0] == '\0')) { return NULL; } - return g_tx_info->contract_name; -} - -const uint8_t *get_contract_addr(void) { - return g_tx_info->contract_addr; + return tx_info->contract_name; } -const char *get_deploy_date(void) { - if (g_tx_info->deploy_date[0] == '\0') { +const uint8_t *get_contract_addr(const s_tx_info *tx_info) { + if (tx_info == NULL) { return NULL; } - return g_tx_info->deploy_date; + return tx_info->contract_addr; } -cx_hash_t *get_fields_hash_ctx(void) { - return (cx_hash_t *) &g_tx_info->fields_hash_ctx; +const char *get_deploy_date(const s_tx_info *tx_info) { + if ((tx_info == NULL) || (tx_info->deploy_date[0] == '\0')) { + return NULL; + } + return tx_info->deploy_date; } -bool validate_instruction_hash(void) { - uint8_t hash[sizeof(g_tx_info->fields_hash)]; - - if (g_tx_info == NULL) return false; - if (cx_hash_no_throw((cx_hash_t *) &g_tx_info->fields_hash_ctx, - CX_LAST, - NULL, - 0, - hash, - sizeof(hash)) != CX_OK) { - return false; - } - return memcmp(g_tx_info->fields_hash, hash, sizeof(hash)) == 0; +void delete_tx_info(s_tx_info *node) { + app_mem_free(node); } diff --git a/src_features/generic_tx_parser/gtp_tx_info.h b/src_features/generic_tx_parser/gtp_tx_info.h index 4b1f01b8a..1f8245f1e 100644 --- a/src_features/generic_tx_parser/gtp_tx_info.h +++ b/src_features/generic_tx_parser/gtp_tx_info.h @@ -7,6 +7,8 @@ #include "calldata.h" #include "tlv.h" #include "signature.h" +#include "list.h" +#include "gtp_field.h" typedef struct { uint8_t version; @@ -23,7 +25,6 @@ typedef struct { char deploy_date[4 + 1 + 2 + 1 + 2 + 1]; uint8_t signature_len; uint8_t signature[ECDSA_SIGNATURE_MAX_LENGTH]; - cx_sha3_t fields_hash_ctx; } s_tx_info; typedef struct { @@ -32,17 +33,14 @@ typedef struct { s_tx_info *tx_info; } s_tx_info_ctx; -extern s_tx_info *g_tx_info; - bool handle_tx_info_struct(const s_tlv_data *data, s_tx_info_ctx *context); bool verify_tx_info_struct(const s_tx_info_ctx *context); -const char *get_operation_type(void); -const char *get_creator_name(void); -const char *get_creator_legal_name(void); -const char *get_creator_url(void); -const char *get_contract_name(void); -const uint8_t *get_contract_addr(void); -const char *get_deploy_date(void); -cx_hash_t *get_fields_hash_ctx(void); -bool validate_instruction_hash(void); +const char *get_operation_type(const s_tx_info *tx_info); +const char *get_creator_name(const s_tx_info *tx_info); +const char *get_creator_legal_name(const s_tx_info *tx_info); +const char *get_creator_url(const s_tx_info *tx_info); +const char *get_contract_name(const s_tx_info *tx_info); +const uint8_t *get_contract_addr(const s_tx_info *tx_info); +const char *get_deploy_date(const s_tx_info *tx_info); +void delete_tx_info(s_tx_info *node); diff --git a/src_features/generic_tx_parser/gtp_value.c b/src_features/generic_tx_parser/gtp_value.c index bc52be4d4..29a3fd754 100644 --- a/src_features/generic_tx_parser/gtp_value.c +++ b/src_features/generic_tx_parser/gtp_value.c @@ -8,6 +8,7 @@ #include "mem.h" #include "mem_utils.h" #include "ui_utils.h" +#include "tx_ctx.h" enum { TAG_VERSION = 0x00, @@ -105,49 +106,43 @@ bool handle_value_struct(const s_tlv_data *data, s_value_context *context) { return ret; } -// have to be declared here since it is not stored anywhere else -static uint8_t *from_address = NULL; - bool value_get(const s_value *value, s_parsed_value_collection *collection) { - bool ret; - switch (value->source) { case SOURCE_CALLDATA: collection->size = 0; - ret = data_path_get(&value->data_path, collection); + if (!data_path_get(&value->data_path, collection)) { + return false; + } break; case SOURCE_RLP: switch (value->container_path) { case CP_FROM: - if (from_address == NULL) { - if ((from_address = app_mem_alloc(ADDRESS_LENGTH)) == NULL) { - return false; // Memory allocation failed - } - } - if ((ret = get_public_key(from_address, ADDRESS_LENGTH) == APDU_RESPONSE_OK)) { - collection->value[0].ptr = from_address; - collection->value[0].length = ADDRESS_LENGTH; - collection->size = 1; + if (((collection->value[0].ptr = get_current_tx_from())) == NULL) { + return false; } + collection->value[0].length = ADDRESS_LENGTH; + collection->size = 1; break; case CP_TO: - collection->value[0].ptr = tmpContent.txContent.destination; - collection->value[0].length = tmpContent.txContent.destinationLength; + if ((collection->value[0].ptr = get_current_tx_to()) == NULL) { + return false; + } + collection->value[0].length = ADDRESS_LENGTH; collection->size = 1; - ret = true; break; case CP_VALUE: - collection->value[0].ptr = tmpContent.txContent.value.value; - collection->value[0].length = tmpContent.txContent.value.length; + if ((collection->value[0].ptr = get_current_tx_amount()) == NULL) { + return false; + } + collection->value[0].length = INT256_LENGTH; collection->size = 1; - ret = true; break; default: - ret = false; + return false; } break; @@ -155,20 +150,16 @@ bool value_get(const s_value *value, s_parsed_value_collection *collection) { collection->value[0].ptr = value->constant.buf; collection->value[0].length = value->constant.size; collection->size = 1; - ret = true; break; default: - ret = false; + return false; } - return ret; + return true; } void value_cleanup(const s_value *value, const s_parsed_value_collection *collection) { if (value->source == SOURCE_CALLDATA) { data_path_cleanup(collection); - } else if ((value->source == SOURCE_RLP && value->container_path == CP_FROM)) { - // No specific cleanup needed for RLP source - mem_buffer_cleanup((void **) &from_address); } } diff --git a/src_features/generic_tx_parser/tx_ctx.c b/src_features/generic_tx_parser/tx_ctx.c new file mode 100644 index 000000000..2a851b78a --- /dev/null +++ b/src_features/generic_tx_parser/tx_ctx.c @@ -0,0 +1,190 @@ +#include "tx_ctx.h" +#include "mem.h" +#include "gtp_field_table.h" +#include "proxy_info.h" +#include "common_ui.h" // ui_gcs_cleanup +#include "shared_context.h" // appState +#include "utils.h" // buf_shrink_expand +#include "getPublicKey.h" +#include "context_712.h" + +static s_tx_ctx *g_tx_ctx_list = NULL; +static s_tx_ctx *g_tx_ctx_current = NULL; +s_calldata *g_parked_calldata = NULL; + +bool tx_ctx_is_root(void) { + return (g_tx_ctx_list != NULL) && (g_tx_ctx_current == g_tx_ctx_list); +} + +size_t get_tx_ctx_count(void) { + return flist_size((s_flist_node **) &g_tx_ctx_list); +} + +cx_hash_t *get_fields_hash_ctx(void) { + return (cx_hash_t *) &g_tx_ctx_current->fields_hash_ctx; +} + +const s_tx_info *get_current_tx_info(void) { + if (g_tx_ctx_current == NULL) return NULL; + return g_tx_ctx_current->tx_info; +} + +s_calldata *get_current_calldata(void) { + if (g_tx_ctx_current == NULL) return NULL; + return g_tx_ctx_current->calldata; +} + +const uint8_t *get_current_tx_from(void) { + if (g_tx_ctx_current == NULL) return NULL; + return g_tx_ctx_current->from; +} + +const uint8_t *get_current_tx_to(void) { + if (g_tx_ctx_current == NULL) return NULL; + return g_tx_ctx_current->to; +} + +const uint8_t *get_current_tx_amount(void) { + if (g_tx_ctx_current == NULL) return NULL; + return g_tx_ctx_current->amount; +} + +static bool validate_inst_hash_on(const s_tx_ctx *tx_ctx) { + cx_sha3_t hash_ctx; + uint8_t hash[sizeof(tx_ctx->tx_info->fields_hash)]; + + if ((tx_ctx == NULL) || (tx_ctx->tx_info == NULL)) return false; + // copy it locally, because the cx_hash call will modify it + memcpy(&hash_ctx, &tx_ctx->fields_hash_ctx, sizeof(hash_ctx)); + if (cx_hash_no_throw((cx_hash_t *) &hash_ctx, CX_LAST, NULL, 0, hash, sizeof(hash)) != CX_OK) { + return false; + } + return memcmp(tx_ctx->tx_info->fields_hash, hash, sizeof(hash)) == 0; +} + +bool validate_instruction_hash(void) { + return validate_inst_hash_on(g_tx_ctx_current); +} + +static void delete_tx_ctx(s_tx_ctx *node) { + if (node->tx_info != NULL) { + delete_tx_info(node->tx_info); + } + if (node->calldata != NULL) { + calldata_delete(node->calldata); + } + app_mem_free(node); +} + +void tx_ctx_pop(void) { + s_flist_node *old_current = (s_flist_node *) g_tx_ctx_current; + + // TODO: make doubly linked to simply get the prev one + for (s_flist_node *tmp = (s_flist_node *) g_tx_ctx_list; tmp != NULL; tmp = tmp->next) { + if (tmp->next == old_current) { + g_tx_ctx_current = (s_tx_ctx *) tmp; + break; + } + } + flist_remove((s_flist_node **) &g_tx_ctx_list, old_current, (f_list_node_del) &delete_tx_ctx); + // set proper current pointer when list becomes empty + if (g_tx_ctx_list == NULL) g_tx_ctx_current = NULL; +} + +bool find_matching_tx_ctx(const uint8_t *contract_addr, + const uint8_t *selector, + const uint64_t *chain_id) { + const uint8_t *proxy_implem; + + for (s_tx_ctx *tmp = g_tx_ctx_list; tmp != NULL; + tmp = (s_tx_ctx *) ((s_flist_node *) tmp)->next) { + proxy_implem = get_implem_contract(chain_id, tmp->to, selector); + if ((memcmp((proxy_implem != NULL) ? proxy_implem : tmp->to, + contract_addr, + ADDRESS_LENGTH) == 0) && + (memcmp(selector, tmp->calldata->selector, CALLDATA_SELECTOR_SIZE) == 0) && + (*chain_id == tmp->chain_id)) { + g_tx_ctx_current = tmp; + return true; + } + } + return false; +} + +void tx_ctx_cleanup(void) { + flist_clear((s_flist_node **) &g_tx_ctx_list, (f_list_node_del) &delete_tx_ctx); + g_tx_ctx_current = NULL; +} + +bool set_tx_info_into_tx_ctx(s_tx_info *tx_info) { + if (g_tx_ctx_current == NULL) return false; + g_tx_ctx_current->tx_info = tx_info; + if (tx_ctx_is_root()) { + if (appState == APP_STATE_SIGNING_EIP712) { + return set_intent_field(tx_info->operation_type); + } + } else { + return set_intent_field(tx_info->operation_type); + } + return true; +} + +bool tx_ctx_init(s_calldata *calldata, + const uint8_t *from, + const uint8_t *to, + const uint8_t *amount, + const uint64_t *chain_id) { + s_tx_ctx *node; + s_eip712_calldata_info *calldata_info; + + if ((node = app_mem_alloc(sizeof(*node))) == NULL) { + return false; + } + explicit_bzero(node, sizeof(*node)); + node->calldata = calldata; + if (get_tx_ctx_count() == 0) { + get_public_key(node->from, ADDRESS_LENGTH); + if (appState == APP_STATE_SIGNING_EIP712) { + calldata_info = get_current_calldata_info(); + if (!calldata_info_all_received(calldata_info) || calldata_info->processed) { + app_mem_free(node); + return false; + } + calldata_info->processed = true; + } + } else { + // as default, copy value from last tx context + const s_tx_ctx *tmp = g_tx_ctx_list; + while (((const s_flist_node *) tmp)->next != NULL) { + tmp = (const s_tx_ctx *) ((const s_flist_node *) tmp)->next; + } + memcpy(node->from, tmp->from, sizeof(node->from)); + memcpy(node->to, tmp->to, sizeof(node->to)); + memcpy(node->amount, tmp->amount, sizeof(node->amount)); + node->chain_id = tmp->chain_id; + } + + if (from != NULL) memcpy(node->from, from, sizeof(node->from)); + if (to != NULL) memcpy(node->to, to, sizeof(node->to)); + if (amount != NULL) memcpy(node->amount, amount, sizeof(node->amount)); + if (chain_id != NULL) node->chain_id = *chain_id; + + if (cx_sha3_init_no_throw(&node->fields_hash_ctx, 256) != CX_OK) { + app_mem_free(node); + return false; + } + flist_push_back((s_flist_node **) &g_tx_ctx_list, (s_flist_node *) node); + g_tx_ctx_current = node; + if ((appState == APP_STATE_SIGNING_TX) && tx_ctx_is_root()) { + return field_table_init(); + } + return true; +} + +void gcs_cleanup(void) { + ui_gcs_cleanup(); + field_table_cleanup(); + tx_ctx_cleanup(); + // just in case + if (g_parked_calldata != NULL) calldata_delete(g_parked_calldata); +} diff --git a/src_features/generic_tx_parser/tx_ctx.h b/src_features/generic_tx_parser/tx_ctx.h new file mode 100644 index 000000000..4f439c3ee --- /dev/null +++ b/src_features/generic_tx_parser/tx_ctx.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include "cx.h" +#include "list.h" +#include "common_utils.h" // ADDRESS_LENGTH, INT256_LENGTH +#include "gtp_tx_info.h" +#include "calldata.h" +#include "gtp_field.h" + +typedef struct { + s_flist_node _list; + s_tx_info *tx_info; + s_calldata *calldata; + uint8_t from[ADDRESS_LENGTH]; + uint8_t to[ADDRESS_LENGTH]; + uint8_t amount[INT256_LENGTH]; + uint64_t chain_id; + + cx_sha3_t fields_hash_ctx; +} s_tx_ctx; + +extern s_calldata *g_parked_calldata; + +bool tx_ctx_is_root(void); +size_t get_tx_ctx_count(void); +cx_hash_t *get_fields_hash_ctx(void); +const s_tx_info *get_current_tx_info(void); +s_calldata *get_current_calldata(void); +const uint8_t *get_current_tx_from(void); +const uint8_t *get_current_tx_to(void); +const uint8_t *get_current_tx_amount(void); +bool validate_instruction_hash(void); +void tx_ctx_pop(void); +bool find_matching_tx_ctx(const uint8_t *contract_addr, + const uint8_t *selector, + const uint64_t *chain_id); +bool set_tx_info_into_tx_ctx(s_tx_info *tx_info); +bool tx_ctx_init(s_calldata *calldata, + const uint8_t *from, + const uint8_t *to, + const uint8_t *amount, + const uint64_t *chain_id); +void gcs_cleanup(void); diff --git a/src_features/provide_enum_value/enum_value.c b/src_features/provide_enum_value/enum_value.c index bb2849ad6..0b27dcebe 100644 --- a/src_features/provide_enum_value/enum_value.c +++ b/src_features/provide_enum_value/enum_value.c @@ -4,6 +4,7 @@ #include "utils.h" #include "ui_utils.h" #include "mem_utils.h" +#include "proxy_info.h" enum { TAG_VERSION = 0x00, @@ -173,8 +174,13 @@ const char *get_matching_enum_name(const uint64_t *chain_id, const uint8_t *selector, uint8_t id, uint8_t value) { + const uint8_t *proxy_implem; + + proxy_implem = get_implem_contract(chain_id, contract_addr, selector); if ((g_enum_value != NULL) && (*chain_id == g_enum_value->chain_id) && - (memcmp(contract_addr, g_enum_value->contract_addr, ADDRESS_LENGTH) == 0) && + (memcmp((proxy_implem != NULL) ? proxy_implem : contract_addr, + g_enum_value->contract_addr, + ADDRESS_LENGTH) == 0) && (memcmp(selector, g_enum_value->selector, SELECTOR_SIZE) == 0) && (id == g_enum_value->id) && (value == g_enum_value->value)) { return g_enum_value->name; diff --git a/src_features/provide_network_info/cmd_network_info.c b/src_features/provide_network_info/cmd_network_info.c index 0bf598c2c..c024a5511 100644 --- a/src_features/provide_network_info/cmd_network_info.c +++ b/src_features/provide_network_info/cmd_network_info.c @@ -45,7 +45,11 @@ static bool check_icon_header(const uint8_t *data, uint16_t length, uint16_t *bu width = U2LE(data, 0); height = U2LE(data, 2); #ifdef SCREEN_SIZE_WALLET +#ifdef TARGET_APEX + expected_px = 48; +#else expected_px = 64; +#endif #else expected_px = 14; #endif @@ -138,7 +142,9 @@ static uint16_t handle_first_icon_chunk(const uint8_t *data, uint8_t length) { return APDU_RESPONSE_INVALID_DATA; } - if (mem_buffer_allocate((void **) &(g_icon_bitmap[g_current_network_slot]), img_len) == false) { + // Do not track the allocation in logs, because this buffer is expected to stay allocated + if (mem_buffer_persistent((void **) &(g_icon_bitmap[g_current_network_slot]), img_len) == + false) { PRINTF("Error: Not enough memory for icon bitmap!\n"); return APDU_RESPONSE_INSUFFICIENT_MEMORY; } diff --git a/src_features/provide_network_info/network_info.c b/src_features/provide_network_info/network_info.c index bfb3fd96e..f8290171f 100644 --- a/src_features/provide_network_info/network_info.c +++ b/src_features/provide_network_info/network_info.c @@ -269,8 +269,9 @@ bool verify_network_info_struct(const s_network_info_ctx *context) { } // Free if already allocated, and reallocate the new size - if (mem_buffer_allocate((void **) &(DYNAMIC_NETWORK_INFO[g_current_network_slot]), - sizeof(network_info_t)) == false) { + // Do not track the allocation in logs, because this buffer is expected to stay allocated + if (mem_buffer_persistent((void **) &(DYNAMIC_NETWORK_INFO[g_current_network_slot]), + sizeof(network_info_t)) == false) { PRINTF("Memory allocation failed for icon hash\n"); return false; } diff --git a/src_features/provide_safe_account/cmd_safe_account.c b/src_features/provide_safe_account/cmd_safe_account.c new file mode 100644 index 000000000..b62e89a28 --- /dev/null +++ b/src_features/provide_safe_account/cmd_safe_account.c @@ -0,0 +1,101 @@ +#ifdef HAVE_SAFE_ACCOUNT + +#include "cmd_safe_account.h" +#include "safe_descriptor.h" +#include "signer_descriptor.h" +#include "apdu_constants.h" +#include "tlv_apdu.h" +#include "common_ui.h" + +#define SAFE_DESCRIPTOR 0x00 +#define SIGNER_DESCRIPTOR 0x01 + +/** + * @brief Handle Safe Account APDU. + * + * @param[in] p1 APDU parameter 1 (indicates First or following chunk) + * @param[in] p2 APDU parameter 2 (indicates Safe or Signers descriptor) + * @param[in] data buffer received + * @param[in] length of the buffer + * @param[out] flags APDU flags + * @return whether the handling was successful + */ +uint16_t handle_safe_account(uint8_t p1, + uint8_t p2, + const uint8_t *data, + uint8_t length, + uint32_t *flags) { + uint16_t sw = APDU_RESPONSE_INTERNAL_ERROR; + + // Check error cases + if (p1 != P1_FIRST_CHUNK && p1 != P1_FOLLOWING_CHUNK) { + PRINTF("Error: Invalid P1 (%u)\n", p1); + return APDU_RESPONSE_INVALID_P1_P2; + } + switch (p2) { + case SAFE_DESCRIPTOR: + if (SAFE_DESC != NULL) { + PRINTF("Error: Safe descriptor already exists!\n"); + sw = APDU_RESPONSE_FILE_ALREADY_EXIST; + } else { + sw = APDU_RESPONSE_OK; // No error for P1_SAFE_DESCRIPTOR if SAFE_DESC is NULL + } + break; + case SIGNER_DESCRIPTOR: + if (SAFE_DESC == NULL) { + PRINTF("Error: Safe descriptor does not exist!\n"); + sw = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + } else if (SIGNER_DESC.data != NULL) { + PRINTF("Error: Signer descriptor already exists!\n"); + sw = APDU_RESPONSE_FILE_ALREADY_EXIST; + } else { + sw = APDU_RESPONSE_OK; // No error for P1_SAFE_DESCRIPTOR if SAFE_DESC is NULL + } + break; + } + + if (sw != APDU_RESPONSE_OK) { + return sw; // Return early if there is an error + } + + // Handle the Safe or Signer descriptor based on P1 + switch (p2) { + case SAFE_DESCRIPTOR: + if (!tlv_from_apdu(p1 == P1_FIRST_CHUNK, length, data, &handle_safe_tlv_payload)) { + sw = APDU_RESPONSE_INVALID_DATA; + } else { + sw = APDU_RESPONSE_OK; + } + break; + case SIGNER_DESCRIPTOR: + if (!tlv_from_apdu(p1 == P1_FIRST_CHUNK, length, data, &handle_signer_tlv_payload)) { + sw = APDU_RESPONSE_INVALID_DATA; + } else { + sw = APDU_RESPONSE_OK; + } + break; + default: + PRINTF("Error: Unexpected P1 (%u)!\n", p1); + sw = APDU_RESPONSE_INVALID_P1_P2; + break; + } + + // Handle display when all data is received + if (SIGNER_DESC.is_valid) { + ui_display_safe_account(); + *flags |= IO_ASYNCH_REPLY; + sw = APDU_NO_RESPONSE; + } + return sw; +} + +/** + * @brief Clear the Safe Account memory. + * + */ +void clear_safe_account(void) { + clear_safe_descriptor(); + clear_signer_descriptor(); +} + +#endif // HAVE_SAFE_ACCOUNT diff --git a/src_features/provide_safe_account/cmd_safe_account.h b/src_features/provide_safe_account/cmd_safe_account.h new file mode 100644 index 000000000..412d94dca --- /dev/null +++ b/src_features/provide_safe_account/cmd_safe_account.h @@ -0,0 +1,7 @@ +#pragma once + +#ifdef HAVE_SAFE_ACCOUNT + +void clear_safe_account(void); + +#endif // HAVE_SAFE_ACCOUNT diff --git a/src_features/provide_safe_account/safe_descriptor.c b/src_features/provide_safe_account/safe_descriptor.c new file mode 100644 index 000000000..21b59b67b --- /dev/null +++ b/src_features/provide_safe_account/safe_descriptor.c @@ -0,0 +1,426 @@ +#ifdef HAVE_SAFE_ACCOUNT + +#include "safe_descriptor.h" +#include "apdu_constants.h" +#include "hash_bytes.h" +#include "public_keys.h" +#include "challenge.h" +#include "tlv.h" +#include "tlv_apdu.h" +#include "utils.h" +#include "nbgl_use_case.h" +#include "os_pki.h" +#include "ui_callbacks.h" +#include "signature.h" +#include "read.h" +#include "mem.h" + +#define TYPE_LESM_ACCOUNT_INFO 0x27 +#define STRUCT_VERSION 0x01 + +#define MAX_THRESHOLD 100 +#define MAX_SIGNERS 100 + +enum { + TAG_STRUCTURE_TYPE = 0x01, + TAG_STRUCTURE_VERSION = 0x02, + TAG_CHALLENGE = 0x12, + TAG_ADDRESS = 0x22, + TAG_THRESHOLD = 0xa0, + TAG_SIGNERS_COUNT = 0xa1, + TAG_ROLE = 0xa2, + TAG_DER_SIGNATURE = 0x15, +}; + +enum { + BIT_STRUCTURE_TYPE, + BIT_STRUCTURE_VERSION, + BIT_CHALLENGE, + BIT_ADDRESS, + BIT_THRESHOLD, + BIT_SIGNERS_COUNT, + BIT_ROLE, + BIT_DER_SIGNATURE, +}; + +typedef struct { + safe_descriptor_t *safe; + uint8_t sig_size; + uint8_t *sig; + cx_sha256_t hash_ctx; + uint32_t rcv_flags; +} s_safe_ctx; + +// Global structure to store the Safe Descriptor +safe_descriptor_t *SAFE_DESC = NULL; + +// Macros to check the field length +#define CHECK_FIELD_LENGTH(tag, len, expected) \ + do { \ + if (len != expected) { \ + PRINTF("%s Size mismatch!\n", tag); \ + return false; \ + } \ + } while (0) +#define CHECK_FIELD_OVERFLOW(tag, len, max) \ + do { \ + if (len > max) { \ + PRINTF("%s Size overflow!\n", tag); \ + return false; \ + } \ + } while (0) + +// Macro to check the field value +#define CHECK_FIELD_VALUE(tag, value, expected) \ + do { \ + if (value != expected) { \ + PRINTF("%s Value mismatch!\n", tag); \ + return false; \ + } \ + } while (0) + +// Macro to check the field value +#define CHECK_EMPTY_BUFFER(tag, field, len) \ + do { \ + uint8_t empty[ADDRESS_LENGTH] = {0}; \ + if (memcmp(field, empty, len) == 0) { \ + PRINTF("%s Zero buffer!\n", tag); \ + return false; \ + } \ + } while (0) + +// Macro to copy the field +#define COPY_FIELD(field, data) \ + do { \ + memmove((void *) field, data->value, data->length); \ + } while (0) + +/** + * @brief Handler for tag \ref STRUCTURE_TYPE. + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_struct_type(const s_tlv_data *data, s_safe_ctx *context) { + CHECK_FIELD_LENGTH("STRUCTURE_TYPE", data->length, 1); + CHECK_FIELD_VALUE("STRUCTURE_TYPE", data->value[0], TYPE_LESM_ACCOUNT_INFO); + context->rcv_flags |= SET_BIT(BIT_STRUCTURE_TYPE); + return true; +} + +/** + * @brief Handler for tag \ref STRUCTURE_VERSION. + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_struct_version(const s_tlv_data *data, s_safe_ctx *context) { + CHECK_FIELD_LENGTH("STRUCTURE_VERSION", data->length, 1); + CHECK_FIELD_VALUE("STRUCTURE_VERSION", data->value[0], STRUCT_VERSION); + context->rcv_flags |= SET_BIT(BIT_STRUCTURE_VERSION); + return true; +} + +/** + * @brief Handler for tag \ref CHALLENGE. + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_challenge(const s_tlv_data *data, s_safe_ctx *context) { + uint8_t buf[sizeof(uint32_t)]; + + CHECK_FIELD_LENGTH("CHALLENGE", data->length, sizeof(uint32_t)); + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + context->rcv_flags |= SET_BIT(BIT_CHALLENGE); + return (read_u32_be(buf, 0) == get_challenge()); +} + +/** + * @brief Handler for tag \ref ADDRESS. + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_address(const s_tlv_data *data, s_safe_ctx *context) { + CHECK_FIELD_LENGTH("ADDRESS", data->length, ADDRESS_LENGTH); + CHECK_EMPTY_BUFFER("ADDRESS", data->value, data->length); + COPY_FIELD(context->safe->address, data); + context->rcv_flags |= SET_BIT(BIT_ADDRESS); + return true; +} + +/** + * @brief Handler for tag \ref THRESHOLD. + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_threshold(const s_tlv_data *data, s_safe_ctx *context) { + uint8_t buf[sizeof(context->safe->threshold)]; + CHECK_FIELD_OVERFLOW("THRESHOLD", data->length, sizeof(context->safe->threshold)); + if (data->length > sizeof(context->safe->threshold)) { + PRINTF("THRESHOLD length must be 1 or 2 bytes\n"); + return false; + } + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + context->safe->threshold = read_u16_be(buf, 0); + if (context->safe->threshold == 0) { + PRINTF("THRESHOLD cannot be 0\n"); + return false; + } + if (context->safe->threshold > MAX_THRESHOLD) { + PRINTF("THRESHOLD cannot be greater than %d\n", MAX_THRESHOLD); + return false; + } + context->rcv_flags |= SET_BIT(BIT_THRESHOLD); + return true; +} + +/** + * @brief Handler for tag \ref SIGNERS_COUNT. + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_signers_count(const s_tlv_data *data, s_safe_ctx *context) { + uint8_t buf[sizeof(context->safe->signers_count)]; + CHECK_FIELD_OVERFLOW("SIGNERS_COUNT", data->length, sizeof(context->safe->signers_count)); + if (data->length > sizeof(context->safe->signers_count)) { + PRINTF("SIGNERS_COUNT length must be 1 or 2 bytes\n"); + return false; + } + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + context->safe->signers_count = read_u16_be(buf, 0); + if (context->safe->signers_count == 0) { + PRINTF("SIGNERS_COUNT cannot be 0\n"); + return false; + } + if (context->safe->signers_count > MAX_SIGNERS) { + PRINTF("SIGNERS_COUNT cannot be greater than %d\n", MAX_SIGNERS); + return false; + } + context->rcv_flags |= SET_BIT(BIT_SIGNERS_COUNT); + return true; +} + +/** + * @brief Handler for tag \ref ROLE. + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_role(const s_tlv_data *data, s_safe_ctx *context) { + CHECK_FIELD_LENGTH("ROLE", data->length, sizeof(context->safe->role)); + context->safe->role = data->value[0]; + if (context->safe->role > ROLE_MAX) { + PRINTF("ROLE cannot be greater than %d\n", ROLE_MAX); + return false; + } + context->rcv_flags |= SET_BIT(BIT_ROLE); + return true; +} + +/** + * Handler for tag \ref DER_SIGNATURE + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_signature(const s_tlv_data *data, s_safe_ctx *context) { + CHECK_FIELD_OVERFLOW("DER_SIGNATURE", data->length, ECDSA_SIGNATURE_MAX_LENGTH); + context->sig_size = data->length; + context->sig = (uint8_t *) data->value; + context->rcv_flags |= SET_BIT(BIT_DER_SIGNATURE); + return true; +} + +/** + * @brief Verify the payload signature + * + * Verify the SHA-256 hash of the payload against the public key + * + * @param[in] context Safe context + * @return whether it was successful + */ +static bool verify_signature(const s_safe_ctx *context) { + uint8_t hash[INT256_LENGTH]; + cx_err_t error = CX_INTERNAL_ERROR; + bool ret_code = false; + + CX_CHECK( + cx_hash_no_throw((cx_hash_t *) &context->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH)); + + CX_CHECK(check_signature_with_pubkey("Safe descriptor", + hash, + sizeof(hash), + NULL, + 0, + CERTIFICATE_PUBLIC_KEY_USAGE_LES_MULTISIG, + (uint8_t *) (context->sig), + context->sig_size)); + + ret_code = true; +end: + return ret_code; +} + +/** + * @brief Verify the received fields + * + * Check the mandatory fields are present + * + * @param[in] context Safe context + * @return whether it was successful + */ +static bool verify_fields(const s_safe_ctx *context) { + uint32_t expected_fields; + + expected_fields = (1 << BIT_STRUCTURE_TYPE) | (1 << BIT_STRUCTURE_VERSION) | + (1 << BIT_CHALLENGE) | (1 << BIT_ADDRESS) | (1 << BIT_THRESHOLD) | + (1 << BIT_SIGNERS_COUNT) | (1 << BIT_ROLE) | (1 << BIT_DER_SIGNATURE); + + return ((context->rcv_flags & expected_fields) == expected_fields); +} + +/** + * @brief Print the Safe descriptor. + * + * @param[in] context Safe context + * Only for debug purpose. + */ +static void print_safe_info(const s_safe_ctx *context) { + UNUSED(context); + PRINTF("****************************************************************************\n"); + PRINTF("[SAFE ACCOUNT] - Retrieved Safe Descriptor:\n"); + PRINTF("[SAFE ACCOUNT] - Address: %.*h\n", ADDRESS_LENGTH, context->safe->address); + PRINTF("[SAFE ACCOUNT] - Threshold: %d (0x%x)\n", + context->safe->threshold, + context->safe->threshold); + PRINTF("[SAFE ACCOUNT] - Signers count: %d (0x%x)\n", + context->safe->signers_count, + context->safe->signers_count); + PRINTF("[SAFE ACCOUNT] - Role: %d (%s)\n", + context->safe->role, + ROLE_STR(context->safe->role)); +} + +/** + * @brief Verify the struct + * + * Verify the SHA-256 hash of the payload against the public key + * + * @param[in] context Safe context + * @return whether it was successful + */ +static bool verify_safe_struct(const s_safe_ctx *context) { + if (!verify_fields(context)) { + PRINTF("Error: Missing mandatory fields in Safe descriptor!\n"); + return false; + } + + if (!verify_signature(context)) { + PRINTF("Error: Signature verification failed for Safe descriptor!\n"); + return false; + } + print_safe_info(context); + return true; +} + +/** + * @brief Parse the received Safe Descriptor TLV. + * + * @param[in] data the tlv data + * @param[in] context Safe context + * @return whether the handling was successful + */ +static bool handle_safe_tlv(const s_tlv_data *data, s_safe_ctx *context) { + bool ret = false; + + switch (data->tag) { + case TAG_STRUCTURE_TYPE: + ret = handle_struct_type(data, context); + break; + case TAG_STRUCTURE_VERSION: + ret = handle_struct_version(data, context); + break; + case TAG_CHALLENGE: + ret = handle_challenge(data, context); + break; + case TAG_ADDRESS: + ret = handle_address(data, context); + break; + case TAG_THRESHOLD: + ret = handle_threshold(data, context); + break; + case TAG_SIGNERS_COUNT: + ret = handle_signers_count(data, context); + break; + case TAG_ROLE: + ret = handle_role(data, context); + break; + case TAG_DER_SIGNATURE: + ret = handle_signature(data, context); + break; + default: + PRINTF(TLV_TAG_ERROR_MSG, data->tag); + break; + } + if ((ret == true) && (data->tag != TAG_DER_SIGNATURE)) { + hash_nbytes(data->raw, data->raw_size, (cx_hash_t *) &context->hash_ctx); + } + return ret; +} + +/** + * @brief Parse the TLV payload containing the Safe descriptor. + * + * @param[in] payload buffer received + * @param[in] size of the buffer + * @return whether the TLV payload was handled successfully or not + */ +bool handle_safe_tlv_payload(const uint8_t *payload, uint16_t size) { + bool ret = false; + s_safe_ctx ctx = {0}; + + // Init the structure + SAFE_DESC = app_mem_alloc(sizeof(safe_descriptor_t)); + if (SAFE_DESC == NULL) { + PRINTF("Error: Memory allocation failed for Safe Descriptor!\n"); + return false; + } + explicit_bzero(SAFE_DESC, sizeof(safe_descriptor_t)); + ctx.safe = SAFE_DESC; + // Initialize the hash context + cx_sha256_init(&ctx.hash_ctx); + + ret = tlv_parse(payload, size, (f_tlv_data_handler) &handle_safe_tlv, &ctx); + if (ret) { + ret = verify_safe_struct(&ctx); + } + if (!ret) { + clear_safe_descriptor(); + } + return ret; +} + +/** + * @brief Clear the Safe memory. + * + */ +void clear_safe_descriptor(void) { + if (SAFE_DESC != NULL) { + app_mem_free(SAFE_DESC); + SAFE_DESC = NULL; + } +} + +#endif // HAVE_SAFE_ACCOUNT diff --git a/src_features/provide_safe_account/safe_descriptor.h b/src_features/provide_safe_account/safe_descriptor.h new file mode 100644 index 000000000..4b132bd8e --- /dev/null +++ b/src_features/provide_safe_account/safe_descriptor.h @@ -0,0 +1,33 @@ +#pragma once + +#ifdef HAVE_SAFE_ACCOUNT + +#include +#include "common_utils.h" + +// clang-format off +typedef enum { + ROLE_SIGNER, + ROLE_PROPOSER, + ROLE_MAX +} safe_role_t; + +#define ROLE_STR(x) \ + (x == ROLE_SIGNER ? "Signer" : \ + x == ROLE_PROPOSER ? "Proposer": \ + "Unknown") + +typedef struct { + const char address[ADDRESS_LENGTH]; + uint16_t threshold; + uint16_t signers_count; + safe_role_t role; +} safe_descriptor_t; +// clang-format on + +extern safe_descriptor_t *SAFE_DESC; + +bool handle_safe_tlv_payload(const uint8_t *payload, uint16_t size); +void clear_safe_descriptor(void); + +#endif // HAVE_SAFE_ACCOUNT diff --git a/src_features/provide_safe_account/signer_descriptor.c b/src_features/provide_safe_account/signer_descriptor.c new file mode 100644 index 000000000..e0ad82b22 --- /dev/null +++ b/src_features/provide_safe_account/signer_descriptor.c @@ -0,0 +1,355 @@ +#ifdef HAVE_SAFE_ACCOUNT + +#include "signer_descriptor.h" +#include "safe_descriptor.h" +#include "apdu_constants.h" +#include "hash_bytes.h" +#include "public_keys.h" +#include "challenge.h" +#include "tlv.h" +#include "tlv_apdu.h" +#include "utils.h" +#include "nbgl_use_case.h" +#include "os_pki.h" +#include "ui_callbacks.h" +#include "signature.h" +#include "read.h" +#include "mem.h" + +#define TYPE_VERIFIABLE_ADDRESS 0x27 +#define STRUCT_VERSION 0x01 + +enum { + TAG_STRUCTURE_TYPE = 0x01, + TAG_STRUCTURE_VERSION = 0x02, + TAG_CHALLENGE = 0x12, + TAG_ADDRESS = 0x22, + TAG_DER_SIGNATURE = 0x15, +}; + +enum { + BIT_STRUCTURE_TYPE, + BIT_STRUCTURE_VERSION, + BIT_CHALLENGE, + BIT_ADDRESS, + BIT_DER_SIGNATURE, +}; + +typedef struct { + signers_descriptor_t *signers; + uint8_t addess_count; + uint8_t sig_size; + uint8_t *sig; + cx_sha256_t hash_ctx; + uint32_t rcv_flags; +} s_signer_ctx; + +// Global structure to store the Signer Descriptor +signers_descriptor_t SIGNER_DESC = {0}; + +// Macros to check the field length +#define CHECK_FIELD_LENGTH(tag, len, expected) \ + do { \ + if (len != expected) { \ + PRINTF("%s Size mismatch!\n", tag); \ + return false; \ + } \ + } while (0) +#define CHECK_FIELD_OVERFLOW(tag, len, max) \ + do { \ + if (len >= max) { \ + PRINTF("%s Size overflow!\n", tag); \ + return false; \ + } \ + } while (0) + +// Macro to check the field value +#define CHECK_FIELD_VALUE(tag, value, expected) \ + do { \ + if (value != expected) { \ + PRINTF("%s Value mismatch!\n", tag); \ + return false; \ + } \ + } while (0) + +// Macro to check the field value +#define CHECK_EMPTY_BUFFER(tag, field, len) \ + do { \ + uint8_t empty[ADDRESS_LENGTH] = {0}; \ + if (memcmp(field, empty, len) == 0) { \ + PRINTF("%s Zero buffer!\n", tag); \ + return false; \ + } \ + } while (0) + +// Macro to copy the field +#define COPY_FIELD(field, data) \ + do { \ + memmove((void *) field, data->value, data->length); \ + } while (0) + +/** + * @brief Handler for tag \ref STRUCTURE_TYPE. + * + * @param[in] data the tlv data + * @param[in] context Signer context + * @return whether the handling was successful + */ +static bool handle_struct_type(const s_tlv_data *data, s_signer_ctx *context) { + CHECK_FIELD_LENGTH("STRUCTURE_TYPE", data->length, 1); + CHECK_FIELD_VALUE("STRUCTURE_TYPE", data->value[0], TYPE_VERIFIABLE_ADDRESS); + context->rcv_flags |= SET_BIT(BIT_STRUCTURE_TYPE); + return true; +} + +/** + * @brief Handler for tag \ref STRUCTURE_VERSION. + * + * @param[in] data the tlv data + * @param[in] context Signer context + * @return whether the handling was successful + */ +static bool handle_struct_version(const s_tlv_data *data, s_signer_ctx *context) { + CHECK_FIELD_LENGTH("STRUCTURE_VERSION", data->length, 1); + CHECK_FIELD_VALUE("STRUCTURE_VERSION", data->value[0], STRUCT_VERSION); + context->rcv_flags |= SET_BIT(BIT_STRUCTURE_VERSION); + return true; +} + +/** + * @brief Handler for tag \ref CHALLENGE. + * + * @param[in] data the tlv data + * @param[in] context Signer context + * @return whether the handling was successful + */ +static bool handle_challenge(const s_tlv_data *data, s_signer_ctx *context) { + uint8_t buf[sizeof(uint32_t)]; + + CHECK_FIELD_LENGTH("CHALLENGE", data->length, sizeof(uint32_t)); + buf_shrink_expand(data->value, data->length, buf, sizeof(buf)); + context->rcv_flags |= SET_BIT(BIT_CHALLENGE); + return (read_u32_be(buf, 0) == get_challenge()); +} + +/** + * @brief Handler for tag \ref ADDRESS. + * + * @param[in] data the tlv data + * @param[in] context Signer context + * @return whether the handling was successful + */ +static bool handle_address(const s_tlv_data *data, s_signer_ctx *context) { + CHECK_FIELD_LENGTH("ADDRESS", data->length, ADDRESS_LENGTH); + CHECK_EMPTY_BUFFER("ADDRESS", data->value, data->length); + if (context->addess_count >= SAFE_DESC->signers_count) { + PRINTF("Error: Too many addresses in Signer descriptor!\n"); + return false; + } + COPY_FIELD(context->signers->data[context->addess_count++].address, data); + context->rcv_flags |= SET_BIT(BIT_ADDRESS); + return true; +} + +/** + * Handler for tag \ref DER_SIGNATURE + * + * @param[in] data the tlv data + * @param[in] context Signer context + * @return whether the handling was successful + */ +static bool handle_signature(const s_tlv_data *data, s_signer_ctx *context) { + CHECK_FIELD_OVERFLOW("DER_SIGNATURE", data->length, ECDSA_SIGNATURE_MAX_LENGTH); + context->sig_size = data->length; + context->sig = (uint8_t *) data->value; + context->rcv_flags |= SET_BIT(BIT_DER_SIGNATURE); + return true; +} + +/** + * @brief Verify the payload signature + * + * Verify the SHA-256 hash of the payload against the public key + * + * @param[in] context Signer context + * @return whether it was successful + */ +static bool verify_signature(const s_signer_ctx *context) { + uint8_t hash[INT256_LENGTH]; + cx_err_t error = CX_INTERNAL_ERROR; + bool ret_code = false; + + CX_CHECK( + cx_hash_no_throw((cx_hash_t *) &context->hash_ctx, CX_LAST, NULL, 0, hash, INT256_LENGTH)); + + CX_CHECK(check_signature_with_pubkey("Signer descriptor", + hash, + sizeof(hash), + NULL, + 0, + CERTIFICATE_PUBLIC_KEY_USAGE_LES_MULTISIG, + (uint8_t *) (context->sig), + context->sig_size)); + + ret_code = true; +end: + return ret_code; +} + +/** + * @brief Verify the received fields + * + * Check the mandatory fields are present + * + * @param[in] context Signer context + * @return whether it was successful + */ +static bool verify_fields(const s_signer_ctx *context) { + uint32_t expected_fields; + + expected_fields = (1 << BIT_STRUCTURE_TYPE) | (1 << BIT_STRUCTURE_VERSION) | + (1 << BIT_CHALLENGE) | (1 << BIT_ADDRESS) | (1 << BIT_DER_SIGNATURE); + + return ((context->rcv_flags & expected_fields) == expected_fields); +} + +/** + * @brief Print the Signer descriptor. + * + * @param[in] context Signer context + * Only for debug purpose. + */ +static void print_signer_info(const s_signer_ctx *context) { + uint8_t i = 0; + UNUSED(context); + + PRINTF("****************************************************************************\n"); + PRINTF("[SAFE ACCOUNT] - Retrieved Signer Descriptor:\n"); + for (i = 0; i < context->addess_count; i++) { + PRINTF("[SAFE ACCOUNT] - Address[%d]: %.*h\n", + i, + ADDRESS_LENGTH, + context->signers->data[i].address); + } +} + +/** + * @brief Verify the struct + * + * Verify the SHA-256 hash of the payload against the public key + * + * @param[in] context Signer context + * @return whether it was successful + */ +static bool verify_signer_struct(const s_signer_ctx *context) { + if (!verify_fields(context)) { + PRINTF("Error: Missing mandatory fields in Signer descriptor!\n"); + return false; + } + if (!verify_signature(context)) { + PRINTF("Error: Signature verification failed for Signer descriptor!\n"); + return false; + } + if (context->addess_count < SAFE_DESC->signers_count) { + PRINTF("Error: Too few addresses in Signer descriptor!\n"); + return false; + } + context->signers->is_valid = true; + print_signer_info(context); + return true; +} + +/** + * @brief Parse the received Signer Descriptor TLV. + * + * @param[in] data the tlv data + * @param[in] context Signer context + * @return whether the handling was successful + */ +static bool handle_signer_tlv(const s_tlv_data *data, s_signer_ctx *context) { + bool ret = false; + + switch (data->tag) { + case TAG_STRUCTURE_TYPE: + ret = handle_struct_type(data, context); + break; + case TAG_STRUCTURE_VERSION: + ret = handle_struct_version(data, context); + break; + case TAG_CHALLENGE: + ret = handle_challenge(data, context); + break; + case TAG_ADDRESS: + ret = handle_address(data, context); + break; + case TAG_DER_SIGNATURE: + ret = handle_signature(data, context); + break; + default: + PRINTF(TLV_TAG_ERROR_MSG, data->tag); + break; + } + if ((ret == true) && (data->tag != TAG_DER_SIGNATURE)) { + hash_nbytes(data->raw, data->raw_size, (cx_hash_t *) &context->hash_ctx); + } + return ret; +} + +/** + * @brief Parse the TLV payload containing the Signer descriptor. + * + * @param[in] payload buffer received + * @param[in] size of the buffer + * @return whether the TLV payload was handled successfully or not + */ +bool handle_signer_tlv_payload(const uint8_t *payload, uint16_t size) { + bool ret = false; + s_signer_ctx ctx = {0}; + + if (SAFE_DESC == NULL) { + PRINTF("Error: Safe descriptor doesn't exist!\n"); + return false; + } + if (SAFE_DESC->signers_count == 0) { + PRINTF("Error: Safe descriptor doesn't contain any Signers!\n"); + return false; + } + if (SIGNER_DESC.data != NULL) { + PRINTF("Error: Signer descriptors already exist!\n"); + return false; + } + // Init the structure + SIGNER_DESC.data = app_mem_alloc(SAFE_DESC->signers_count * sizeof(signer_data_t)); + if (SIGNER_DESC.data == NULL) { + PRINTF("Error: Memory allocation failed for Signer Descriptor!\n"); + return false; + } + explicit_bzero(SIGNER_DESC.data, SAFE_DESC->signers_count * sizeof(signer_data_t)); + SIGNER_DESC.is_valid = false; + ctx.signers = &SIGNER_DESC; + // Initialize the hash context + cx_sha256_init(&ctx.hash_ctx); + + ret = tlv_parse(payload, size, (f_tlv_data_handler) &handle_signer_tlv, &ctx); + if (ret) { + ret = verify_signer_struct(&ctx); + } + if (!ret) { + clear_signer_descriptor(); + } + return ret; +} + +/** + * @brief Clear the Signer memory. + * + */ +void clear_signer_descriptor(void) { + if (SIGNER_DESC.data != NULL) { + app_mem_free(SIGNER_DESC.data); + SIGNER_DESC.data = NULL; + } + explicit_bzero(&SIGNER_DESC, sizeof(SIGNER_DESC)); +} + +#endif // HAVE_SAFE_ACCOUNT diff --git a/src_features/provide_safe_account/signer_descriptor.h b/src_features/provide_safe_account/signer_descriptor.h new file mode 100644 index 000000000..be5252486 --- /dev/null +++ b/src_features/provide_safe_account/signer_descriptor.h @@ -0,0 +1,22 @@ +#pragma once + +#ifdef HAVE_SAFE_ACCOUNT + +#include +#include "common_utils.h" + +typedef struct { + char address[ADDRESS_LENGTH]; +} signer_data_t; + +typedef struct { + signer_data_t *data; + bool is_valid; +} signers_descriptor_t; + +extern signers_descriptor_t SIGNER_DESC; + +bool handle_signer_tlv_payload(const uint8_t *payload, uint16_t size); +void clear_signer_descriptor(void); + +#endif // HAVE_SAFE_ACCOUNT diff --git a/src_features/provide_trusted_name/trusted_name.c b/src_features/provide_trusted_name/trusted_name.c index 96e9b92d3..f2cc2a12e 100644 --- a/src_features/provide_trusted_name/trusted_name.c +++ b/src_features/provide_trusted_name/trusted_name.c @@ -56,6 +56,11 @@ typedef enum { s_trusted_name_info *g_trusted_name_info = NULL; char *g_trusted_name = NULL; +void trusted_name_cleanup(void) { + mem_buffer_cleanup((void **) &g_trusted_name); + mem_buffer_cleanup((void **) &g_trusted_name_info); +} + static bool matching_type(e_name_type type, uint8_t type_count, const e_name_type *types) { for (int i = 0; i < type_count; ++i) { if (type == types[i]) return true; diff --git a/src_features/provide_trusted_name/trusted_name.h b/src_features/provide_trusted_name/trusted_name.h index add5c5851..865f425d5 100644 --- a/src_features/provide_trusted_name/trusted_name.h +++ b/src_features/provide_trusted_name/trusted_name.h @@ -66,3 +66,4 @@ extern char *g_trusted_name; bool handle_trusted_name_struct(const s_tlv_data *data, s_trusted_name_ctx *context); bool verify_trusted_name_struct(const s_trusted_name_ctx *ctx); +void trusted_name_cleanup(void); diff --git a/src_features/provide_tx_simulation/cmd_get_tx_simulation.c b/src_features/provide_tx_simulation/cmd_get_tx_simulation.c index 3bb7b30bb..29c9c4bc7 100644 --- a/src_features/provide_tx_simulation/cmd_get_tx_simulation.c +++ b/src_features/provide_tx_simulation/cmd_get_tx_simulation.c @@ -12,6 +12,7 @@ #include "os_pki.h" #include "network.h" #include "ui_callbacks.h" +#include "ui_nbgl.h" #define TYPE_TX_SIMULATION 0x09 #define STRUCT_VERSION 0x01 @@ -571,7 +572,7 @@ void clear_tx_simulation(void) { * * @return whether it was successful */ -bool check_tx_simulation_hash(void) { +static bool check_tx_simulation_hash(void) { uint8_t *hash = NULL; uint8_t *hash2 = NULL; @@ -623,7 +624,7 @@ bool check_tx_simulation_hash(void) { * * @return whether it was successful */ -bool check_tx_simulation_from_address(void) { +static bool check_tx_simulation_from_address(void) { uint8_t msg_sender[ADDRESS_LENGTH] = {0}; if (get_public_key(msg_sender, sizeof(msg_sender)) != APDU_RESPONSE_OK) { PRINTF("[TX SIMU] Unable to get the public key!\n"); @@ -645,19 +646,28 @@ bool check_tx_simulation_from_address(void) { } /** - * @brief Check the TX vs Simulation parameters (CHAIN_ID, TX_HASH). + * @brief Check the CHAIN_ID vs Simulation payload. * - * @param[in] checkTxHash flag to check the TX_HASH - * @param[in] checkFromAddr flag to check the FROM address * @return whether it was successful */ -static bool check_tx_simulation_params(bool checkTxHash, bool checkFromAddr) { +static bool check_tx_simulation_chain_id(void) { uint64_t chain_id = get_tx_chain_id(); - - if (!N_storage.tx_check_enable) { - // Transaction Checks disabled - return true; + // Check Chain_ID in case of a standard transaction (No EIP191, No EIP712) + if ((appState == APP_STATE_SIGNING_TX) && (TX_SIMULATION.chain_id != chain_id)) { + PRINTF("[TX SIMU] Chain_ID mismatch: %u != %u\n", TX_SIMULATION.chain_id, chain_id); + PRINTF("[TX SIMU] Force Score to UNKNOWN\n"); + TX_SIMULATION.risk = RISK_UNKNOWN; + return false; } + return true; +} + +/** + * @brief Check the validity of the Simulation parameters. + * + * @return whether it was successful + */ +static bool check_tx_simulation_validity(void) { switch (TX_SIMULATION.type) { case SIMU_TYPE_TRANSACTION: if (appState != APP_STATE_SIGNING_TX) { @@ -693,22 +703,30 @@ static bool check_tx_simulation_params(bool checkTxHash, bool checkFromAddr) { PRINTF("[TX SIMU] Force Score to UNKNOWN\n"); return false; } - // Check Chain_ID in case of a standard transaction (No EIP191, No EIP712) - if ((appState == APP_STATE_SIGNING_TX) && (TX_SIMULATION.chain_id != chain_id)) { - PRINTF("[TX SIMU] Chain_ID mismatch: %u != %u\n", TX_SIMULATION.chain_id, chain_id); - PRINTF("[TX SIMU] Force Score to UNKNOWN\n"); - TX_SIMULATION.risk = RISK_UNKNOWN; + return true; +} + +/** + * @brief Check the TX vs Simulation parameters (CHAIN_ID, TX_HASH). + * + * @return whether it was successful + */ +static bool check_tx_simulation_params(void) { + if (!N_storage.tx_check_enable) { + // Transaction Checks disabled + return true; + } + if (check_tx_simulation_validity() == false) { return false; } - if (checkFromAddr) { - if (check_tx_simulation_from_address() == false) { - return false; - } + if (check_tx_simulation_chain_id() == false) { + return false; } - if (checkTxHash) { - if (check_tx_simulation_hash() == false) { - return false; - } + if (check_tx_simulation_from_address() == false) { + return false; + } + if (check_tx_simulation_hash() == false) { + return false; } return true; } @@ -716,36 +734,33 @@ static bool check_tx_simulation_params(bool checkTxHash, bool checkFromAddr) { /** * @brief Configure the warning predefined set for the NBGL review flows. * - * @param[in] p_warning Warning structure for NBGL review flows - * @param[in] checkTxHash flag to check the TX_HASH - * @param[in] checkFromAddr flag to check the FROM address */ -void set_tx_simulation_warning(nbgl_warning_t *p_warning, bool checkTxHash, bool checkFromAddr) { +void set_tx_simulation_warning(void) { if (!N_storage.tx_check_enable) { // Transaction Checks disabled return; } // Transaction Checks enabled => Verify parameters of the Transaction - check_tx_simulation_params(checkTxHash, checkFromAddr); + check_tx_simulation_params(); switch (TX_SIMULATION.risk) { case RISK_UNKNOWN: - p_warning->predefinedSet |= SET_BIT(W3C_ISSUE_WARN); + warning.predefinedSet |= SET_BIT(W3C_ISSUE_WARN); break; case RISK_BENIGN: - p_warning->predefinedSet |= SET_BIT(W3C_NO_THREAT_WARN); + warning.predefinedSet |= SET_BIT(W3C_NO_THREAT_WARN); break; case RISK_WARNING: - p_warning->predefinedSet |= SET_BIT(W3C_RISK_DETECTED_WARN); + warning.predefinedSet |= SET_BIT(W3C_RISK_DETECTED_WARN); break; case RISK_MALICIOUS: - p_warning->predefinedSet |= SET_BIT(W3C_THREAT_DETECTED_WARN); + warning.predefinedSet |= SET_BIT(W3C_THREAT_DETECTED_WARN); break; default: break; } - p_warning->reportProvider = PIC(TX_SIMULATION.partner); - p_warning->providerMessage = get_tx_simulation_category_str(); - p_warning->reportUrl = PIC(TX_SIMULATION.tiny_url); + warning.reportProvider = PIC(TX_SIMULATION.partner); + warning.providerMessage = get_tx_simulation_category_str(); + warning.reportUrl = PIC(TX_SIMULATION.tiny_url); } /** diff --git a/src_features/provide_tx_simulation/cmd_get_tx_simulation.h b/src_features/provide_tx_simulation/cmd_get_tx_simulation.h index 85e6c439e..8d385300d 100644 --- a/src_features/provide_tx_simulation/cmd_get_tx_simulation.h +++ b/src_features/provide_tx_simulation/cmd_get_tx_simulation.h @@ -5,7 +5,6 @@ #include #include #include "common_utils.h" -#include "nbgl_use_case.h" #include "os_pki.h" #define HASH_SIZE 32 @@ -54,13 +53,10 @@ uint16_t handle_tx_simulation(uint8_t p1, uint8_t length, unsigned int *flags); void handle_tx_simulation_opt_in(bool response_expected); -void ui_tx_simulation_error(nbgl_choiceCallback_t callback); void ui_tx_simulation_opt_in(bool response_expected); void clear_tx_simulation(void); -bool check_tx_simulation_hash(void); -bool check_tx_simulation_from_address(void); -void set_tx_simulation_warning(nbgl_warning_t *p_warning, bool checkTxHash, bool checkFromAddr); +void set_tx_simulation_warning(void); const char *get_tx_simulation_risk_str(void); const char *get_tx_simulation_category_str(void); diff --git a/src_features/signMessageEIP712/commands_712.c b/src_features/signMessageEIP712/commands_712.c index b8ebdcbc2..8c2d9f2a6 100644 --- a/src_features/signMessageEIP712/commands_712.c +++ b/src_features/signMessageEIP712/commands_712.c @@ -9,10 +9,12 @@ #include "common_ui.h" // ui_idle #include "manage_asset_info.h" #include "ui_callbacks.h" +#include "tx_ctx.h" // get_tx_ctx_count // APDUs P1 -#define P1_COMPLETE 0x00 -#define P1_PARTIAL 0xFF +#define P1_COMPLETE 0x00 +#define P1_PARTIAL 0xFF +#define P1_DISCARDED 0x01 // APDUs P2 #define P2_DEF_NAME 0x00 @@ -23,6 +25,13 @@ #define P2_FILT_ACTIVATE 0x00 #define P2_FILT_DISCARDED_PATH 0x01 #define P2_FILT_MESSAGE_INFO 0x0F +#define P2_FILT_CALLDATA_SPENDER 0xF4 +#define P2_FILT_CALLDATA_AMOUNT 0xF5 +#define P2_FILT_CALLDATA_SELECTOR 0xF6 +#define P2_FILT_CALLDATA_CHAIN_ID 0xF7 +#define P2_FILT_CALLDATA_CALLEE 0xF8 +#define P2_FILT_CALLDATA_VALUE 0xF9 +#define P2_FILT_CALLDATA_INFO 0xFA #define P2_FILT_CONTRACT_NAME 0xFB #define P2_FILT_DATE_TIME 0xFC #define P2_FILT_AMOUNT_JOIN_TOKEN 0xFD @@ -204,27 +213,48 @@ uint16_t handle_eip712_filtering(uint8_t p1, reply_apdu = false; } break; + case P2_FILT_CALLDATA_SPENDER: + ret = filtering_calldata_spender(cdata, length, p1 == P1_DISCARDED, &path_crc); + break; + case P2_FILT_CALLDATA_AMOUNT: + ret = filtering_calldata_amount(cdata, length, p1 == P1_DISCARDED, &path_crc); + break; + case P2_FILT_CALLDATA_SELECTOR: + ret = filtering_calldata_selector(cdata, length, p1 == P1_DISCARDED, &path_crc); + break; + case P2_FILT_CALLDATA_CHAIN_ID: + ret = filtering_calldata_chain_id(cdata, length, p1 == P1_DISCARDED, &path_crc); + break; + case P2_FILT_CALLDATA_CALLEE: + ret = filtering_calldata_callee(cdata, length, p1 == P1_DISCARDED, &path_crc); + break; + case P2_FILT_CALLDATA_VALUE: + ret = filtering_calldata_value(cdata, length, p1 == P1_DISCARDED, &path_crc); + break; + case P2_FILT_CALLDATA_INFO: + ret = filtering_calldata_info(cdata, length); + break; case P2_FILT_CONTRACT_NAME: - ret = filtering_trusted_name(cdata, length, p1 == 1, &path_crc); + ret = filtering_trusted_name(cdata, length, p1 == P1_DISCARDED, &path_crc); break; case P2_FILT_DATE_TIME: - ret = filtering_date_time(cdata, length, p1 == 1, &path_crc); + ret = filtering_date_time(cdata, length, p1 == P1_DISCARDED, &path_crc); break; case P2_FILT_AMOUNT_JOIN_TOKEN: - ret = filtering_amount_join_token(cdata, length, p1 == 1, &path_crc); + ret = filtering_amount_join_token(cdata, length, p1 == P1_DISCARDED, &path_crc); break; case P2_FILT_AMOUNT_JOIN_VALUE: - ret = filtering_amount_join_value(cdata, length, p1 == 1, &path_crc); + ret = filtering_amount_join_value(cdata, length, p1 == P1_DISCARDED, &path_crc); break; case P2_FILT_RAW_FIELD: - ret = filtering_raw_field(cdata, length, p1 == 1, &path_crc); + ret = filtering_raw_field(cdata, length, p1 == P1_DISCARDED, &path_crc); break; default: PRINTF("Unknown P2 0x%x\n", p2); apdu_response_code = APDU_RESPONSE_INVALID_P1_P2; ret = false; } - if ((p2 > P2_FILT_MESSAGE_INFO) && ret) { + if ((p2 > P2_FILT_MESSAGE_INFO) && (p2 != P2_FILT_CALLDATA_INFO) && ret) { if (!ui_712_push_new_filter_path(path_crc)) { ret = false; } @@ -260,15 +290,18 @@ uint16_t handle_eip712_sign(const uint8_t *cdata, uint8_t length, uint32_t *flag (ui_712_remaining_filters() != 0)) { PRINTF("%d EIP712 filters are missing\n", ui_712_remaining_filters()); apdu_response_code = APDU_RESPONSE_REF_DATA_NOT_FOUND; + } else if (!all_calldata_info_processed() || (get_tx_ctx_count() != 0)) { + PRINTF("Unprocessed calldata\n"); + apdu_response_code = APDU_RESPONSE_REF_DATA_NOT_FOUND; } else if (parseBip32(cdata, &length, &tmpCtx.messageSigningContext.bip32) == NULL) { apdu_response_code = APDU_RESPONSE_INVALID_DATA; } else { + ret = true; #ifndef SCREEN_SIZE_WALLET if (!N_storage.verbose_eip712 && (ui_712_get_filtering_mode() == EIP712_FILTERING_BASIC)) { - ui_712_message_hash(); + ret = ui_712_message_hash(); } #endif - ret = true; ui_712_end_sign(); } diff --git a/src_features/signMessageEIP712/context_712.h b/src_features/signMessageEIP712/context_712.h index fb7723c69..e9ed113d3 100644 --- a/src_features/signMessageEIP712/context_712.h +++ b/src_features/signMessageEIP712/context_712.h @@ -2,6 +2,7 @@ #include #include "common_utils.h" +#include "list.h" typedef struct { uint8_t contract_addr[ADDRESS_LENGTH]; diff --git a/src_features/signMessageEIP712/field_hash.c b/src_features/signMessageEIP712/field_hash.c index 38b366bdd..8abcf78d0 100644 --- a/src_features/signMessageEIP712/field_hash.c +++ b/src_features/signMessageEIP712/field_hash.c @@ -256,6 +256,7 @@ static bool field_hash_finalize(const s_struct_712_field *field_ptr, bool field_hash(const uint8_t *data, uint8_t data_length, bool partial) { const s_struct_712_field *field_ptr; bool first = fh->state == FHS_IDLE; + uint16_t total_length = 0; if ((fh == NULL) || ((field_ptr = path_get_field()) == NULL)) { apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; @@ -273,6 +274,7 @@ bool field_hash(const uint8_t *data, uint8_t data_length, bool partial) { } data = field_hash_prepare(field_ptr, data, &data_length); + total_length = fh->remaining_size; } if (data_length > fh->remaining_size) { apdu_response_code = APDU_RESPONSE_INVALID_DATA; @@ -283,7 +285,11 @@ bool field_hash(const uint8_t *data, uint8_t data_length, bool partial) { if (IS_DYN(field_ptr->type)) { hash_nbytes(data, data_length, (cx_hash_t *) &global_sha3); } - if (!ui_712_feed_to_display(field_ptr, data, data_length, first, fh->remaining_size == 0)) { + if (!ui_712_feed_to_display(field_ptr, + data, + data_length, + first ? &total_length : NULL, + fh->remaining_size == 0)) { return false; } if (fh->remaining_size == 0) { diff --git a/src_features/signMessageEIP712/filtering.c b/src_features/signMessageEIP712/filtering.c index 2e35e71db..5fd0b9b41 100644 --- a/src_features/signMessageEIP712/filtering.c +++ b/src_features/signMessageEIP712/filtering.c @@ -12,8 +12,17 @@ #include "os_pki.h" #include "trusted_name.h" #include "proxy_info.h" +#include "mem.h" +#include "getPublicKey.h" #define FILT_MAGIC_MESSAGE_INFO 183 +#define FILT_MAGIC_CALLDATA_INFO 55 +#define FILT_MAGIC_CALLDATA_VALUE 66 +#define FILT_MAGIC_CALLDATA_CALLEE 77 +#define FILT_MAGIC_CALLDATA_CHAIN_ID 88 +#define FILT_MAGIC_CALLDATA_SELECTOR 99 +#define FILT_MAGIC_CALLDATA_AMOUNT 110 +#define FILT_MAGIC_CALLDATA_SPENDER 121 #define FILT_MAGIC_AMOUNT_JOIN_TOKEN 11 #define FILT_MAGIC_AMOUNT_JOIN_VALUE 22 #define FILT_MAGIC_DATETIME 33 @@ -232,7 +241,7 @@ bool filtering_message_info(const uint8_t *payload, uint8_t length) { if (!N_storage.verbose_eip712) { ui_712_set_title("Contract", 8); ui_712_set_value(name, name_len); - ui_712_redraw_generic_step(); + return ui_712_redraw_generic_step(); } return true; } @@ -324,6 +333,498 @@ bool filtering_discarded_path(const uint8_t *payload, uint8_t length) { return true; } +/** + * Command to process the upcoming field as a nested TX spender + * + * @param[in] payload the payload to parse + * @param[in] length the payload length + * @param[in] discarded if the filter targets a field that is does not exist (within an empty array) + * @param[out] path_crc pointer to the CRC of the filter path + * @return whether it was successful or not + */ +bool filtering_calldata_spender(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc) { + uint8_t offset = 0; + uint8_t index; + uint8_t sig_len; + const uint8_t *sig; + + if (path_get_root_type() != ROOT_MESSAGE) { + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + return false; + } + + // Parsing + if ((offset + sizeof(index)) > length) { + return false; + } + index = payload[offset++]; + + if ((offset + sizeof(sig_len)) > length) { + return false; + } + sig_len = payload[offset++]; + if ((offset + sig_len) != length) { + return false; + } + sig = &payload[offset]; + + // Verification + cx_sha256_t hash_ctx; + if (!sig_verif_start(&hash_ctx, FILT_MAGIC_CALLDATA_SPENDER)) { + return false; + } + hash_filtering_path((cx_hash_t *) &hash_ctx, discarded, path_crc); + hash_byte(index, (cx_hash_t *) &hash_ctx); + if (!sig_verif_end(&hash_ctx, sig, sig_len)) { + return false; + } + + // Handling + if (get_calldata_info(index) == NULL) { + PRINTF("Error: no matching calldata info (index=%u)\n", index); + return false; + } + ui_712_flag_field(false, false, false, false, false, true); + calldata_info_set_state(index, EIP712_CALLDATA_SPENDER); + return true; +} + +/** + * Command to process the upcoming field as a nested TX amount + * + * @param[in] payload the payload to parse + * @param[in] length the payload length + * @param[in] discarded if the filter targets a field that is does not exist (within an empty array) + * @param[out] path_crc pointer to the CRC of the filter path + * @return whether it was successful or not + */ +bool filtering_calldata_amount(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc) { + uint8_t offset = 0; + uint8_t index; + uint8_t sig_len; + const uint8_t *sig; + + if (path_get_root_type() != ROOT_MESSAGE) { + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + return false; + } + + // Parsing + if ((offset + sizeof(index)) > length) { + return false; + } + index = payload[offset++]; + + if ((offset + sizeof(sig_len)) > length) { + return false; + } + sig_len = payload[offset++]; + if ((offset + sig_len) != length) { + return false; + } + sig = &payload[offset]; + + // Verification + cx_sha256_t hash_ctx; + if (!sig_verif_start(&hash_ctx, FILT_MAGIC_CALLDATA_AMOUNT)) { + return false; + } + hash_filtering_path((cx_hash_t *) &hash_ctx, discarded, path_crc); + hash_byte(index, (cx_hash_t *) &hash_ctx); + if (!sig_verif_end(&hash_ctx, sig, sig_len)) { + return false; + } + + // Handling + if (get_calldata_info(index) == NULL) { + PRINTF("Error: no matching calldata info (index=%u)\n", index); + return false; + } + ui_712_flag_field(false, false, false, false, false, true); + calldata_info_set_state(index, EIP712_CALLDATA_AMOUNT); + return true; +} + +/** + * Command to process the upcoming field as a nested TX calldata selector + * + * @param[in] payload the payload to parse + * @param[in] length the payload length + * @param[in] discarded if the filter targets a field that is does not exist (within an empty array) + * @param[out] path_crc pointer to the CRC of the filter path + * @return whether it was successful or not + */ +bool filtering_calldata_selector(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc) { + uint8_t offset = 0; + uint8_t index; + uint8_t sig_len; + const uint8_t *sig; + + if (path_get_root_type() != ROOT_MESSAGE) { + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + return false; + } + + // Parsing + if ((offset + sizeof(index)) > length) { + return false; + } + index = payload[offset++]; + + if ((offset + sizeof(sig_len)) > length) { + return false; + } + sig_len = payload[offset++]; + if ((offset + sig_len) != length) { + return false; + } + sig = &payload[offset]; + + // Verification + cx_sha256_t hash_ctx; + if (!sig_verif_start(&hash_ctx, FILT_MAGIC_CALLDATA_SELECTOR)) { + return false; + } + hash_filtering_path((cx_hash_t *) &hash_ctx, discarded, path_crc); + hash_byte(index, (cx_hash_t *) &hash_ctx); + if (!sig_verif_end(&hash_ctx, sig, sig_len)) { + return false; + } + + // Handling + if (get_calldata_info(index) == NULL) { + PRINTF("Error: no matching calldata info (index=%u)\n", index); + return false; + } + ui_712_flag_field(false, false, false, false, false, true); + calldata_info_set_state(index, EIP712_CALLDATA_SELECTOR); + return true; +} + +/** + * Command to process the upcoming field as a nested TX chain ID + * + * @param[in] payload the payload to parse + * @param[in] length the payload length + * @param[in] discarded if the filter targets a field that is does not exist (within an empty array) + * @param[out] path_crc pointer to the CRC of the filter path + * @return whether it was successful or not + */ +bool filtering_calldata_chain_id(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc) { + uint8_t offset = 0; + uint8_t index; + uint8_t sig_len; + const uint8_t *sig; + + if (path_get_root_type() != ROOT_MESSAGE) { + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + return false; + } + + // Parsing + if ((offset + sizeof(index)) > length) { + return false; + } + index = payload[offset++]; + + if ((offset + sizeof(sig_len)) > length) { + return false; + } + sig_len = payload[offset++]; + if ((offset + sig_len) != length) { + return false; + } + sig = &payload[offset]; + + // Verification + cx_sha256_t hash_ctx; + if (!sig_verif_start(&hash_ctx, FILT_MAGIC_CALLDATA_CHAIN_ID)) { + return false; + } + hash_filtering_path((cx_hash_t *) &hash_ctx, discarded, path_crc); + hash_byte(index, (cx_hash_t *) &hash_ctx); + if (!sig_verif_end(&hash_ctx, sig, sig_len)) { + return false; + } + + // Handling + if (get_calldata_info(index) == NULL) { + PRINTF("Error: no matching calldata info (index=%u)\n", index); + return false; + } + ui_712_flag_field(false, false, false, false, false, true); + calldata_info_set_state(index, EIP712_CALLDATA_CHAIN_ID); + return true; +} + +/** + * Command to process the upcoming field as a nested TX callee + * + * @param[in] payload the payload to parse + * @param[in] length the payload length + * @param[in] discarded if the filter targets a field that is does not exist (within an empty array) + * @param[out] path_crc pointer to the CRC of the filter path + * @return whether it was successful or not + */ +bool filtering_calldata_callee(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc) { + uint8_t offset = 0; + uint8_t index; + uint8_t sig_len; + const uint8_t *sig; + + if (path_get_root_type() != ROOT_MESSAGE) { + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + return false; + } + + // Parsing + if ((offset + sizeof(index)) > length) { + return false; + } + index = payload[offset++]; + + if ((offset + sizeof(sig_len)) > length) { + return false; + } + sig_len = payload[offset++]; + if ((offset + sig_len) != length) { + return false; + } + sig = &payload[offset]; + + // Verification + cx_sha256_t hash_ctx; + if (!sig_verif_start(&hash_ctx, FILT_MAGIC_CALLDATA_CALLEE)) { + return false; + } + hash_filtering_path((cx_hash_t *) &hash_ctx, discarded, path_crc); + hash_byte(index, (cx_hash_t *) &hash_ctx); + if (!sig_verif_end(&hash_ctx, sig, sig_len)) { + return false; + } + + // Handling + if (get_calldata_info(index) == NULL) { + PRINTF("Error: no matching calldata info (index=%u)\n", index); + return false; + } + ui_712_flag_field(false, false, false, false, false, true); + calldata_info_set_state(index, EIP712_CALLDATA_CALLEE); + return true; +} + +/** + * Command to process the upcoming field as a nested TX calldata + * + * @param[in] payload the payload to parse + * @param[in] length the payload length + * @param[in] discarded if the filter targets a field that is does not exist (within an empty array) + * @param[out] path_crc pointer to the CRC of the filter path + * @return whether it was successful or not + */ +bool filtering_calldata_value(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc) { + uint8_t offset = 0; + uint8_t index; + uint8_t sig_len; + const uint8_t *sig; + + if (path_get_root_type() != ROOT_MESSAGE) { + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + return false; + } + + // Parsing + if ((offset + sizeof(index)) > length) { + return false; + } + index = payload[offset++]; + + if ((offset + sizeof(sig_len)) > length) { + return false; + } + sig_len = payload[offset++]; + if ((offset + sig_len) != length) { + return false; + } + sig = &payload[offset]; + + // Verification + cx_sha256_t hash_ctx; + if (!sig_verif_start(&hash_ctx, FILT_MAGIC_CALLDATA_VALUE)) { + return false; + } + hash_filtering_path((cx_hash_t *) &hash_ctx, discarded, path_crc); + hash_byte(index, (cx_hash_t *) &hash_ctx); + if (!sig_verif_end(&hash_ctx, sig, sig_len)) { + return false; + } + + // Handling + if (get_calldata_info(index) == NULL) { + PRINTF("Error: no matching calldata info (index=%u)\n", index); + return false; + } + ui_712_flag_field(false, false, false, false, false, true); + calldata_info_set_state(index, EIP712_CALLDATA_VALUE); + return true; +} + +/** + * Command to give the calldata info/context (not attached to a field) + * + * @param[in] payload the payload to parse + * @param[in] length the payload length + * @return whether it was successful or not + */ +bool filtering_calldata_info(const uint8_t *payload, uint8_t length) { + uint8_t offset = 0; + uint8_t index; + bool value_flag; + e_calldata_addr_flag callee_flag; + bool chain_id_flag; + bool selector_flag; + bool amount_flag; + e_calldata_addr_flag spender_flag; + uint8_t sig_len; + const uint8_t *sig; + s_eip712_calldata_info *calldata_info; + + if (path_get_root_type() != ROOT_MESSAGE) { + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + return false; + } + + // Parsing + if ((offset + sizeof(index)) > length) { + return false; + } + index = payload[offset++]; + + if ((offset + sizeof(value_flag)) > length) { + return false; + } + value_flag = payload[offset++]; + // mandatory + if (!value_flag) return false; + + if ((offset + sizeof(callee_flag)) > length) { + return false; + } + callee_flag = payload[offset++]; + switch (callee_flag) { + case CALLDATA_FLAG_ADDR_FILTER: + case CALLDATA_FLAG_ADDR_VERIFYING_CONTRACT: + break; + default: + return false; + } + + if ((offset + sizeof(chain_id_flag)) > length) { + return false; + } + chain_id_flag = payload[offset++]; + + if ((offset + sizeof(selector_flag)) > length) { + return false; + } + selector_flag = payload[offset++]; + + if ((offset + sizeof(amount_flag)) > length) { + return false; + } + amount_flag = payload[offset++]; + + if ((offset + sizeof(spender_flag)) > length) { + return false; + } + spender_flag = payload[offset++]; + switch (spender_flag) { + case CALLDATA_FLAG_ADDR_NONE: + case CALLDATA_FLAG_ADDR_FILTER: + case CALLDATA_FLAG_ADDR_VERIFYING_CONTRACT: + break; + default: + return false; + } + + if ((offset + sizeof(sig_len)) > length) { + return false; + } + sig_len = payload[offset++]; + if ((offset + sig_len) != length) { + return false; + } + sig = &payload[offset]; + + // Verification + cx_sha256_t hash_ctx; + if (!sig_verif_start(&hash_ctx, FILT_MAGIC_CALLDATA_INFO)) { + return false; + } + hash_byte(index, (cx_hash_t *) &hash_ctx); + hash_byte(value_flag, (cx_hash_t *) &hash_ctx); + hash_byte(callee_flag, (cx_hash_t *) &hash_ctx); + hash_byte(chain_id_flag, (cx_hash_t *) &hash_ctx); + hash_byte(selector_flag, (cx_hash_t *) &hash_ctx); + hash_byte(amount_flag, (cx_hash_t *) &hash_ctx); + hash_byte(spender_flag, (cx_hash_t *) &hash_ctx); + if (!sig_verif_end(&hash_ctx, sig, sig_len)) { + return false; + } + if ((calldata_info = app_mem_alloc(sizeof(*calldata_info))) == NULL) { + return false; + } + + explicit_bzero(calldata_info, sizeof(*calldata_info)); + calldata_info->index = index; + + if (callee_flag == CALLDATA_FLAG_ADDR_VERIFYING_CONTRACT) { + memcpy(calldata_info->callee, eip712_context->contract_addr, sizeof(calldata_info->callee)); + calldata_info->callee_received = true; + } + if (!chain_id_flag) { + calldata_info->chain_id = eip712_context->chain_id; + calldata_info->chain_id_received = true; + } + if (!selector_flag) calldata_info->selector_received = true; + if (!amount_flag) calldata_info->amount_received = true; + switch (spender_flag) { + case CALLDATA_FLAG_ADDR_VERIFYING_CONTRACT: + memcpy(calldata_info->spender, + eip712_context->contract_addr, + sizeof(calldata_info->spender)); + calldata_info->spender_received = true; + break; + case CALLDATA_FLAG_ADDR_NONE: + get_public_key(calldata_info->spender, sizeof(calldata_info->spender)); + calldata_info->spender_received = true; + break; + default: + break; + } + add_calldata_info(calldata_info); + PRINTF("New calldata info (index=%u)\n", index); + return true; +} + /** * Command to display a field as a trusted name * @@ -443,7 +944,7 @@ bool filtering_trusted_name(const uint8_t *payload, if (name_len > 0) { // don't substitute for an empty name ui_712_set_title(name, name_len); } - ui_712_flag_field(true, name_len > 0, false, false, true); + ui_712_flag_field(true, name_len > 0, false, false, true, false); ui_712_set_trusted_name_requirements(type_count, types, source_count, sources); return true; } @@ -508,7 +1009,7 @@ bool filtering_date_time(const uint8_t *payload, if (name_len > 0) { // don't substitute for an empty name ui_712_set_title(name, name_len); } - ui_712_flag_field(true, name_len > 0, false, true, false); + ui_712_flag_field(true, name_len > 0, false, true, false, false); return true; } @@ -564,7 +1065,7 @@ bool filtering_amount_join_token(const uint8_t *payload, if (!check_typename("address") || !check_token_index(token_idx)) { return false; } - ui_712_flag_field(false, false, true, false, false); + ui_712_flag_field(false, false, true, false, false, false); ui_712_token_join_prepare_addr_check(token_idx); return true; } @@ -651,7 +1152,7 @@ bool filtering_amount_join_value(const uint8_t *payload, if (!check_typename("uint") || !check_token_index(token_idx)) { return false; } - ui_712_flag_field(false, false, true, false, false); + ui_712_flag_field(false, false, true, false, false, false); return ui_712_token_join_prepare_amount(token_idx, name, name_len); } @@ -714,7 +1215,7 @@ bool filtering_raw_field(const uint8_t *payload, if (name_len > 0) { // don't substitute for an empty name ui_712_set_title(name, name_len); } - ui_712_flag_field(true, name_len > 0, false, false, false); + ui_712_flag_field(true, name_len > 0, false, false, false, false); } return true; } diff --git a/src_features/signMessageEIP712/filtering.h b/src_features/signMessageEIP712/filtering.h index 818390c5f..f450bf778 100644 --- a/src_features/signMessageEIP712/filtering.h +++ b/src_features/signMessageEIP712/filtering.h @@ -6,6 +6,31 @@ #define MAX_FILTERS 50 bool filtering_message_info(const uint8_t *payload, uint8_t length); +bool filtering_calldata_spender(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc); +bool filtering_calldata_amount(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc); +bool filtering_calldata_selector(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc); +bool filtering_calldata_chain_id(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc); +bool filtering_calldata_callee(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc); +bool filtering_calldata_value(const uint8_t *payload, + uint8_t length, + bool discarded, + uint32_t *path_crc); +bool filtering_calldata_info(const uint8_t *payload, uint8_t length); bool filtering_trusted_name(const uint8_t *payload, uint8_t length, bool discarded, diff --git a/src_features/signMessageEIP712/ui_logic.c b/src_features/signMessageEIP712/ui_logic.c index 236c2dd25..eb30e8638 100644 --- a/src_features/signMessageEIP712/ui_logic.c +++ b/src_features/signMessageEIP712/ui_logic.c @@ -14,6 +14,10 @@ #include "network.h" #include "time_format.h" #include "list.h" +#include "ui_utils.h" +#include "utils.h" +#include "tx_ctx.h" // g_parked_calldata +#include "read.h" // read_u64_be #define AMOUNT_JOIN_FLAG_TOKEN (1 << 0) #define AMOUNT_JOIN_FLAG_VALUE (1 << 1) @@ -40,6 +44,7 @@ typedef enum { #define UI_712_AMOUNT_JOIN (1 << 2) #define UI_712_DATETIME (1 << 3) #define UI_712_TRUSTED_NAME (1 << 4) +#define UI_712_CALLDATA (1 << 5) typedef struct { s_amount_join *joins; @@ -53,7 +58,6 @@ typedef struct filter_crc { } s_filter_crc; typedef struct { - bool shown; bool end_reached; e_eip712_filtering_mode filtering_mode; uint8_t filters_to_process; @@ -67,6 +71,8 @@ typedef struct { e_name_type tn_types[TN_TYPE_COUNT]; e_name_source tn_sources[TN_SOURCE_COUNT]; s_ui_712_pair *ui_pairs; + s_eip712_calldata_info *calldata_info; + uint8_t calldata_index; } t_ui_context; static t_ui_context *ui_ctx = NULL; @@ -88,6 +94,32 @@ static void delete_amount_join(s_amount_join *join) { app_mem_free(join); } +/** + * Called to fetch the next field if they have not all been processed yet + * + * Also handles the special "Review struct" screen of the verbose mode + * + * @return the next field state + */ +static bool ui_712_next_field(void) { + bool ret = false; + + if (ui_ctx == NULL) { + apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; + } else { + if (ui_ctx->structs_to_review > 0) { + ret = ui_712_review_struct(path_get_nth_field_to_last(ui_ctx->structs_to_review)); + ui_ctx->structs_to_review -= 1; + } else if (!ui_ctx->end_reached) { + handle_eip712_return_code(true); + // So that later when we append to them, we start from an empty string + explicit_bzero(&strings, sizeof(strings)); + ret = true; + } + } + return ret; +} + /** * Checks on the UI context to determine if the next EIP 712 field should be shown * @@ -98,12 +130,12 @@ static bool ui_712_field_shown(void) { if (ui_ctx->filtering_mode == EIP712_FILTERING_BASIC) { #ifdef SCREEN_SIZE_WALLET - if (true) { + ret = true; #else if (N_storage.verbose_eip712 || (path_get_root_type() == ROOT_DOMAIN)) { -#endif ret = true; } +#endif } else { // EIP712_FILTERING_FULL if (ui_ctx->field_flags & UI_712_FIELD_SHOWN) { ret = true; @@ -112,34 +144,6 @@ static bool ui_712_field_shown(void) { return ret; } -/** - * Set UI buffer - * - * @param[in] src source buffer - * @param[in] src_length source buffer size - * @param[in] dst destination buffer - * @param[in] dst_length destination buffer length - * @param[in] explicit_trunc if truncation should be explicitly shown - */ -static void ui_712_set_buf(const char *src, - size_t src_length, - char *dst, - size_t dst_length, - bool explicit_trunc) { - uint8_t cpy_length; - - if (src_length < dst_length) { - cpy_length = src_length; - } else { - cpy_length = dst_length - 1; - } - memcpy(dst, src, cpy_length); - dst[cpy_length] = '\0'; - if (explicit_trunc && (cpy_length < src_length)) { - memcpy(dst + cpy_length - 3, "...", 3); - } -} - /** * Skip the field if needed and reset its UI flags */ @@ -157,17 +161,52 @@ void ui_712_finalize_field(void) { * @param[in] length its length */ void ui_712_set_title(const char *str, size_t length) { - ui_712_set_buf(str, length, strings.tmp.tmp2, sizeof(strings.tmp.tmp2), false); + s_ui_712_pair *new_pair = NULL; + + if (mem_buffer_allocate((void **) &new_pair, sizeof(*new_pair)) == false) { + return; + } + flist_push_back((s_flist_node **) &ui_ctx->ui_pairs, (s_flist_node *) new_pair); + if (mem_buffer_allocate((void **) &new_pair->key, length + 1) == false) { + return; + } + memcpy(new_pair->key, str, length); } /** * Set a new value for the EIP-712 generic UX_STEP * + * @note The parameters may be NULL if the value is already formatted into strings.tmp.tmp + * * @param[in] str the new value * @param[in] length its length */ void ui_712_set_value(const char *str, size_t length) { - ui_712_set_buf(str, length, strings.tmp.tmp, sizeof(strings.tmp.tmp), true); + s_ui_712_pair *tmp = ui_ctx->ui_pairs; + + if (tmp == NULL) { + // No pairs created yet + return; + } + while (((s_flist_node *) tmp)->next != NULL) { + tmp = (s_ui_712_pair *) ((s_flist_node *) tmp)->next; + } + if (tmp->value != NULL) { + PRINTF("Value already exist for tag %s: %s\n", tmp->key, tmp->value); + return; + } + if ((str != NULL) && (length > 0)) { + // buffer is directly provided with parameters + if (mem_buffer_allocate((void **) &tmp->value, length + 1) == false) { + return; + } + memcpy(tmp->value, str, length); + } else if (strlen(strings.tmp.tmp) > 0) { + // Add the value from the global variable strings.tmp.tmp + if ((tmp->value = app_mem_strdup(strings.tmp.tmp)) == NULL) { + return; + } + } } /** @@ -176,7 +215,7 @@ void ui_712_set_value(const char *str, size_t length) { * @return whether it was successful or not */ bool ui_712_redraw_generic_step(void) { - if (!ui_ctx->shown) { // Initialize if it is not already + if (appState != APP_STATE_SIGNING_EIP712) { // Initialize if it is not already if ((ui_ctx->filtering_mode == EIP712_FILTERING_BASIC) && !N_storage.dataAllowed && !N_storage.verbose_eip712) { // Both settings not enabled => Error @@ -185,43 +224,14 @@ bool ui_712_redraw_generic_step(void) { eip712_context->go_home_on_failure = false; return false; } - if (ui_ctx->filtering_mode == EIP712_FILTERING_BASIC) { - ui_712_start_unfiltered(); - } else { - ui_712_start(); - } - ui_ctx->shown = true; + ui_712_start(ui_ctx->filtering_mode); + handle_eip712_return_code(true); } else { - ui_712_switch_to_message(); - } - return true; -} - -/** - * Called to fetch the next field if they have not all been processed yet - * - * Also handles the special "Review struct" screen of the verbose mode - * - * @return the next field state - */ -e_eip712_nfs ui_712_next_field(void) { - e_eip712_nfs state = EIP712_NO_MORE_FIELD; - - if (ui_ctx == NULL) { - apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; - } else { - if (ui_ctx->structs_to_review > 0) { - ui_712_review_struct(path_get_nth_field_to_last(ui_ctx->structs_to_review)); - ui_ctx->structs_to_review -= 1; - state = EIP712_FIELD_LATER; - } else if (!ui_ctx->end_reached) { - handle_eip712_return_code(true); - state = EIP712_FIELD_INCOMING; - // So that later when we append to them, we start from an empty string - explicit_bzero(&strings, sizeof(strings)); + if (ui_712_next_field() == false) { + ui_sign_712(); } } - return state; + return true; } /** @@ -248,7 +258,7 @@ bool ui_712_review_struct(const s_struct_712 *struct_ptr) { /** * Show the hash of the message on the generic UI step */ -void ui_712_message_hash(void) { +bool ui_712_message_hash(void) { const char *title = "Message hash"; ui_712_set_title(title, strlen(title)); @@ -256,8 +266,9 @@ void ui_712_message_hash(void) { sizeof(strings.tmp.tmp), tmpCtx.messageSigningContext712.messageHash, KECCAK256_HASH_BYTESIZE); + ui_712_set_value(NULL, 0); ui_ctx->end_reached = true; - ui_712_redraw_generic_step(); + return ui_712_redraw_generic_step(); } /** @@ -611,20 +622,216 @@ static bool ui_712_format_datetime(const uint8_t *data, return time_format_to_utc(×tamp, strings.tmp.tmp, sizeof(strings.tmp.tmp)); } +static bool handle_fallback_empty_calldata(const s_eip712_calldata_info *calldata_info) { + char *buf = strings.tmp.tmp; + size_t buf_size = sizeof(strings.tmp.tmp); + uint64_t chain_id; + uint8_t decimals; + const char *ticker; + + if (!allzeroes(calldata_info->amount, sizeof(calldata_info->amount))) { + ui_712_set_title("Transaction type", 16); + ui_712_set_value("Send", 4); + + if (calldata_info->chain_id != 0) { + chain_id = calldata_info->chain_id; + } else { + chain_id = eip712_context->chain_id; + } + + ticker = get_displayable_ticker(&chain_id, chainConfig); + decimals = WEI_TO_ETHER; + if (!amountToString(calldata_info->amount, + sizeof(calldata_info->amount), + decimals, + ticker, + buf, + buf_size)) { + return false; + } + ui_712_set_title("Amount", 6); + ui_712_set_value(buf, strlen(buf)); + if (!getEthDisplayableAddress((uint8_t *) calldata_info->callee, + buf, + buf_size, + chainConfig->chainId)) { + return false; + } + ui_712_set_title("To", 2); + ui_712_set_value(buf, strlen(buf)); + } + return true; +} + +static bool update_calldata_value(const uint8_t *data, + uint8_t length, + const uint16_t *complete_length, + bool last, + s_eip712_calldata_info *calldata_info) { + const uint8_t *selector = NULL; + size_t calldata_size; + + if (calldata_info->value_received) return false; + if (complete_length != NULL) { + calldata_size = *complete_length; + if (calldata_size > 0) { + if (calldata_info->selector_received) { + if (allzeroes(calldata_info->selector, sizeof(calldata_info->selector))) { + if ((length < CALLDATA_SELECTOR_SIZE) || + (calldata_size < CALLDATA_SELECTOR_SIZE)) { + return false; + } + selector = data; + data += CALLDATA_SELECTOR_SIZE; + length -= CALLDATA_SELECTOR_SIZE; + calldata_size -= CALLDATA_SELECTOR_SIZE; + } else { + selector = calldata_info->selector; + } + } + if ((g_parked_calldata = calldata_init(calldata_size, selector)) == NULL) { + return false; + } + } + } + if (g_parked_calldata != NULL) { + if (!calldata_append(g_parked_calldata, data, length)) { + return false; + } + } else { + // won't receive a TX info & descriptors about a non-existent calldata + calldata_info->processed = true; + } + if (last) calldata_info->value_received = true; + return true; +} + +static bool update_calldata_callee(const uint8_t *data, + uint8_t length, + bool last, + s_eip712_calldata_info *calldata_info) { + if (calldata_info->callee_received) return false; + if (!last) return false; + buf_shrink_expand(data, length, calldata_info->callee, sizeof(calldata_info->callee)); + calldata_info->callee_received = true; + return true; +} + +static bool update_calldata_chain_id(const uint8_t *data, + uint8_t length, + bool last, + s_eip712_calldata_info *calldata_info) { + uint8_t chain_id_buf[sizeof(uint64_t)]; + + if (calldata_info->chain_id_received) return false; + if (!last) return false; + buf_shrink_expand(data, length, chain_id_buf, sizeof(chain_id_buf)); + calldata_info->chain_id = read_u64_be(chain_id_buf, 0); + calldata_info->chain_id_received = true; + return true; +} + +static bool update_calldata_selector(const uint8_t *data, + uint8_t length, + bool last, + s_eip712_calldata_info *calldata_info) { + if (calldata_info->selector_received) return false; + if (!last) return false; + buf_shrink_expand(data, length, calldata_info->selector, sizeof(calldata_info->selector)); + calldata_info->selector_received = true; + if (calldata_info->value_received) { + calldata_set_selector(g_parked_calldata, calldata_info->selector); + } + return true; +} + +static bool update_calldata_amount(const uint8_t *data, + uint8_t length, + bool last, + s_eip712_calldata_info *calldata_info) { + if (calldata_info->amount_received) return false; + if (!last) return false; + buf_shrink_expand(data, length, calldata_info->amount, sizeof(calldata_info->amount)); + calldata_info->amount_received = true; + return true; +} + +static bool update_calldata_spender(const uint8_t *data, + uint8_t length, + bool last, + s_eip712_calldata_info *calldata_info) { + if (calldata_info->spender_received) return false; + if (!last) return false; + buf_shrink_expand(data, length, calldata_info->spender, sizeof(calldata_info->spender)); + calldata_info->spender_received = true; + return true; +} + +static bool update_calldata(const uint8_t *data, + uint8_t length, + const uint16_t *complete_length, + bool last) { + s_eip712_calldata_info *calldata_info = get_calldata_info(ui_ctx->calldata_index); + + if (calldata_info == NULL) return false; + switch (calldata_info->state) { + case EIP712_CALLDATA_VALUE: + if (!update_calldata_value(data, length, complete_length, last, calldata_info)) + return false; + break; + case EIP712_CALLDATA_CALLEE: + if (!update_calldata_callee(data, length, last, calldata_info)) return false; + break; + case EIP712_CALLDATA_CHAIN_ID: + if (!update_calldata_chain_id(data, length, last, calldata_info)) return false; + break; + case EIP712_CALLDATA_SELECTOR: + if (!update_calldata_selector(data, length, last, calldata_info)) return false; + break; + case EIP712_CALLDATA_AMOUNT: + if (!update_calldata_amount(data, length, last, calldata_info)) return false; + break; + case EIP712_CALLDATA_SPENDER: + if (!update_calldata_spender(data, length, last, calldata_info)) return false; + break; + default: + return false; + } + if (calldata_info_all_received(calldata_info)) { + if (g_parked_calldata == NULL) { + if (!handle_fallback_empty_calldata(calldata_info)) return false; + } else { + if (!tx_ctx_init(g_parked_calldata, + calldata_info->spender, + calldata_info->callee, + calldata_info->amount, + &calldata_info->chain_id)) { + calldata_delete(g_parked_calldata); + g_parked_calldata = NULL; + return false; + } + g_parked_calldata = NULL; + } + } + return true; +} + /** * Formats and feeds the given input data to the display buffers * * @param[in] field_ptr pointer to the new struct field * @param[in] data pointer to the field's raw value * @param[in] length field's raw value byte-length - * @param[in] first if this is the first chunk + * @param[in] complete_length pointer to complete length if first chunk, \ref NULL otherwise * @param[in] last if this is the last chunk */ bool ui_712_feed_to_display(const s_struct_712_field *field_ptr, const uint8_t *data, uint8_t length, - bool first, + const uint16_t *complete_length, bool last) { + bool first = complete_length != NULL; + if (ui_ctx == NULL) { apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED; return false; @@ -699,9 +906,18 @@ bool ui_712_feed_to_display(const s_struct_712_field *field_ptr, } } + if (ui_ctx->field_flags & UI_712_CALLDATA) { + if (!update_calldata(data, length, complete_length, last)) { + return false; + } + } + // Check if this field is supposed to be displayed if (last && ui_712_field_shown()) { - if (!ui_712_redraw_generic_step()) return false; + // This is the last chunk, we can now set the value + ui_712_set_value(NULL, 0); + + return ui_712_redraw_generic_step(); } return true; } @@ -722,7 +938,7 @@ void ui_712_end_sign(void) { if (N_storage.verbose_eip712 || (ui_ctx->filtering_mode == EIP712_FILTERING_FULL)) { #endif ui_ctx->end_reached = true; - ui_712_switch_to_sign(); + ui_sign_712(); } } @@ -737,7 +953,7 @@ bool ui_712_init(void) { if ((ui_ctx = app_mem_alloc(sizeof(*ui_ctx)))) { explicit_bzero(ui_ctx, sizeof(*ui_ctx)); - ui_ctx->filtering_mode = EIP712_FILTERING_BASIC; + ui_712_set_filtering_mode(EIP712_FILTERING_BASIC); explicit_bzero(&strings, sizeof(strings)); } else { apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY; @@ -745,6 +961,10 @@ bool ui_712_init(void) { return ui_ctx != NULL; } +static void delete_calldata_info(s_eip712_calldata_info *node) { + app_mem_free(node); +} + /** * Deinit function that simply unsets the struct pointer to NULL */ @@ -758,6 +978,11 @@ void ui_712_deinit(void) { if (ui_ctx->amount.joins != NULL) flist_clear((s_flist_node **) &ui_ctx->amount.joins, (f_list_node_del) &delete_amount_join); + if (ui_ctx->calldata_info != NULL) { + flist_clear((s_flist_node **) &ui_ctx->calldata_info, + (f_list_node_del) &delete_calldata_info); + gcs_cleanup(); + } app_mem_free(ui_ctx); ui_ctx = NULL; } @@ -766,26 +991,20 @@ void ui_712_deinit(void) { /** * Approve button handling, calls the common handler function then * deinitializes the EIP712 context altogether. - * @param[in] e unused here, just needed to match the UI function signature - * @return unused here, just needed to match the UI function signature */ -unsigned int ui_712_approve() { +void ui_712_approve(void) { ui_712_approve_cb(); eip712_context_deinit(); - return 0; } /** * Reject button handling, calls the common handler function then * deinitializes the EIP712 context altogether. - * @param[in] e unused here, just needed to match the UI function signature - * @return unused here, just needed to match the UI function signature */ -unsigned int ui_712_reject() { +void ui_712_reject(void) { ui_712_reject_cb(); eip712_context_deinit(); - return 0; } /** @@ -801,7 +1020,8 @@ void ui_712_flag_field(bool show, bool name_provided, bool token_join, bool datetime, - bool trusted_name) { + bool trusted_name, + bool calldata) { if (show) { ui_ctx->field_flags |= UI_712_FIELD_SHOWN; } @@ -817,6 +1037,9 @@ void ui_712_flag_field(bool show, if (trusted_name) { ui_ctx->field_flags |= UI_712_TRUSTED_NAME; } + if (calldata) { + ui_ctx->field_flags |= UI_712_CALLDATA; + } } /** @@ -852,12 +1075,7 @@ void ui_712_set_filters_count(uint8_t count) { * @return number of filters */ uint8_t ui_712_remaining_filters(void) { - uint8_t filter_count = 0; - - for (const s_filter_crc *tmp = ui_ctx->filters_crc; tmp != NULL; - tmp = (s_filter_crc *) ((s_flist_node *) tmp)->next) - filter_count += 1; - return ui_ctx->filters_to_process - filter_count; + return ui_ctx->filters_to_process - flist_size((s_flist_node **) &ui_ctx->filters_crc); } /** @@ -1004,39 +1222,78 @@ void ui_712_set_trusted_name_requirements(uint8_t type_count, memcpy(ui_ctx->tn_sources, sources, source_count); } -const s_ui_712_pair *ui_712_get_pairs(void) { - return ui_ctx->ui_pairs; +/** + * Set the tag/value pairs for the review + * + */ +void ui_712_push_pairs(void) { + uint16_t nbPairs = 0; + uint16_t pair = 0; + s_ui_712_pair *tmp = NULL; + + // Initialize the pairs list + nbPairs = flist_size((s_flist_node **) &ui_ctx->ui_pairs); + if (N_storage.displayHash) { + nbPairs += 2; + } + ui_pairs_init(nbPairs); + // Initialize the tag/value pairs from the chain list + tmp = ui_ctx->ui_pairs; + while (tmp != NULL) { + g_pairs[pair].item = tmp->key; + g_pairs[pair].value = tmp->value; + tmp = (s_ui_712_pair *) ((s_flist_node *) tmp)->next; + pair++; + } + if (N_storage.displayHash) { + // Prepare the pairs list with the hashes + eip712_format_hash(pair); + g_pairs[pair].forcePageStart = 1; + } } -bool ui_712_push_new_pair(const char *key, const char *value) { - s_ui_712_pair *new_pair; +void add_calldata_info(s_eip712_calldata_info *node) { + flist_push_back((s_flist_node **) &ui_ctx->calldata_info, (s_flist_node *) node); +} - // allocate pair - if ((new_pair = app_mem_alloc(sizeof(*new_pair))) == NULL) { - return false; +s_eip712_calldata_info *get_calldata_info(uint8_t index) { + for (s_eip712_calldata_info *tmp = ui_ctx->calldata_info; tmp != NULL; + tmp = (s_eip712_calldata_info *) ((s_flist_node *) tmp)->next) { + if (index == tmp->index) { + return tmp; + } } - explicit_bzero(new_pair, sizeof(*new_pair)); - - flist_push_back((s_flist_node **) &ui_ctx->ui_pairs, (s_flist_node *) new_pair); + return NULL; +} - if ((new_pair->key = app_mem_strdup(key)) == NULL) { - return false; - } +s_eip712_calldata_info *get_current_calldata_info(void) { + return get_calldata_info(ui_ctx->calldata_index); +} - if ((new_pair->value = app_mem_strdup(value)) == NULL) { - return false; +bool all_calldata_info_processed(void) { + for (const s_eip712_calldata_info *tmp = ui_ctx->calldata_info; tmp != NULL; + tmp = (const s_eip712_calldata_info *) ((const s_flist_node *) tmp)->next) { + if (!tmp->processed) return false; } return true; } -void ui_712_delete_pairs(size_t keep) { - size_t size; +void calldata_info_set_state(uint8_t index, e_eip712_calldata_state state) { + s_eip712_calldata_info *calldata_info = get_calldata_info(index); - size = flist_size((s_flist_node **) &ui_ctx->ui_pairs); - if (size > 0) { - while (size > keep) { - flist_pop_front((s_flist_node **) &ui_ctx->ui_pairs, (f_list_node_del) &delete_ui_pair); - size -= 1; + ui_ctx->calldata_index = index; + if (calldata_info != NULL) { + calldata_info->state = state; + } +} + +bool calldata_info_all_received(const s_eip712_calldata_info *calldata_info) { + if (calldata_info != NULL) { + if (calldata_info->value_received && calldata_info->callee_received && + calldata_info->chain_id_received && calldata_info->selector_received && + calldata_info->amount_received && calldata_info->spender_received) { + return true; } } + return false; } diff --git a/src_features/signMessageEIP712/ui_logic.h b/src_features/signMessageEIP712/ui_logic.h index 01722dabd..36f918c61 100644 --- a/src_features/signMessageEIP712/ui_logic.h +++ b/src_features/signMessageEIP712/ui_logic.h @@ -7,13 +7,9 @@ #include "typed_data.h" #include "trusted_name.h" #include "list.h" +#include "calldata.h" typedef enum { EIP712_FILTERING_BASIC, EIP712_FILTERING_FULL } e_eip712_filtering_mode; -typedef enum { - EIP712_FIELD_LATER, - EIP712_FIELD_INCOMING, - EIP712_NO_MORE_FIELD -} e_eip712_nfs; // next field state typedef struct ui_712_pair { s_flist_node _list; @@ -21,27 +17,63 @@ typedef struct ui_712_pair { char *value; } s_ui_712_pair; +typedef enum { + CALLDATA_FLAG_ADDR_NONE = 0, + CALLDATA_FLAG_ADDR_FILTER = 1, + CALLDATA_FLAG_ADDR_VERIFYING_CONTRACT = 2, +} e_calldata_addr_flag; + +typedef enum { + EIP712_CALLDATA_VALUE, + EIP712_CALLDATA_CALLEE, + EIP712_CALLDATA_CHAIN_ID, + EIP712_CALLDATA_SELECTOR, + EIP712_CALLDATA_AMOUNT, + EIP712_CALLDATA_SPENDER, +} e_eip712_calldata_state; + +typedef struct { + s_flist_node _list; + uint8_t index; + e_eip712_calldata_state state; + + bool value_received : 1; // value is stored in the calldata linked-list + bool callee_received : 1; + bool chain_id_received : 1; + bool selector_received : 1; + bool amount_received : 1; + bool spender_received : 1; + + bool processed : 1; + + uint8_t callee[ADDRESS_LENGTH]; + uint64_t chain_id; + uint8_t selector[CALLDATA_SELECTOR_SIZE]; + uint8_t amount[INT256_LENGTH]; + uint8_t spender[ADDRESS_LENGTH]; +} s_eip712_calldata_info; + bool ui_712_init(void); void ui_712_deinit(void); -e_eip712_nfs ui_712_next_field(void); bool ui_712_review_struct(const s_struct_712 *struct_ptr); bool ui_712_feed_to_display(const s_struct_712_field *field_ptr, const uint8_t *data, uint8_t length, - bool first, + const uint16_t *complete_length, bool last); void ui_712_end_sign(void); -unsigned int ui_712_approve(); -unsigned int ui_712_reject(); +void ui_712_approve(void); +void ui_712_reject(void); void ui_712_set_title(const char *str, size_t length); void ui_712_set_value(const char *str, size_t length); -void ui_712_message_hash(void); +bool ui_712_message_hash(void); bool ui_712_redraw_generic_step(void); void ui_712_flag_field(bool show, bool name_provided, bool token_join, bool datetime, - bool contract_name); + bool trusted_name, + bool calldata); void ui_712_field_flags_reset(void); void ui_712_finalize_field(void); void ui_712_set_filtering_mode(e_eip712_filtering_mode mode); @@ -61,6 +93,10 @@ void ui_712_set_trusted_name_requirements(uint8_t type_count, const e_name_type *types, uint8_t source_count, const e_name_source *sources); -const s_ui_712_pair *ui_712_get_pairs(void); -bool ui_712_push_new_pair(const char *key, const char *value); -void ui_712_delete_pairs(size_t keep); +void ui_712_push_pairs(void); +void add_calldata_info(s_eip712_calldata_info *node); +s_eip712_calldata_info *get_calldata_info(uint8_t index); +s_eip712_calldata_info *get_current_calldata_info(void); +bool all_calldata_info_processed(void); +void calldata_info_set_state(uint8_t index, e_eip712_calldata_state state); +bool calldata_info_all_received(const s_eip712_calldata_info *calldata_info); diff --git a/src_features/signMessageEIP712_common/common_712.c b/src_features/signMessageEIP712_common/common_712.c index 3e43a659d..a6199d587 100644 --- a/src_features/signMessageEIP712_common/common_712.c +++ b/src_features/signMessageEIP712_common/common_712.c @@ -2,11 +2,15 @@ #include "os_io_seproxyhal.h" #include "crypto_helpers.h" #include "ui_callbacks.h" -#include "common_712.h" +#include "utils.h" +#include "ui_utils.h" +#include "ui_logic.h" +#include "ui_nbgl.h" +#include "cmd_get_tx_simulation.h" static const uint8_t EIP_712_MAGIC[] = {0x19, 0x01}; -unsigned int ui_712_approve_cb(void) { +void ui_712_approve_cb(void) { uint8_t hash[INT256_LENGTH]; io_seproxyhal_io_heartbeat(); @@ -50,11 +54,11 @@ unsigned int ui_712_approve_cb(void) { if (info & CX_ECCINFO_xGTn) { G_io_apdu_buffer[0] += 2; } - return io_seproxyhal_send_status(APDU_RESPONSE_OK, 65, true, false); + io_seproxyhal_send_status(APDU_RESPONSE_OK, 65, true, false); } -unsigned int ui_712_reject_cb(void) { - return io_seproxyhal_send_status(APDU_RESPONSE_CONDITION_NOT_SATISFIED, 0, true, false); +void ui_712_reject_cb(void) { + io_seproxyhal_send_status(APDU_RESPONSE_CONDITION_NOT_SATISFIED, 0, true, false); } static char *format_hash(const uint8_t *hash, char *buffer, size_t buffer_size, size_t offset) { @@ -62,27 +66,35 @@ static char *format_hash(const uint8_t *hash, char *buffer, size_t buffer_size, return buffer + offset; } -void eip712_format_hash(nbgl_contentTagValue_t *pairs, - uint8_t nbPairs, - nbgl_contentTagValueList_t *pairs_list) { - explicit_bzero(pairs, sizeof(nbgl_contentTagValue_t) * nbPairs); - explicit_bzero(pairs_list, sizeof(nbgl_contentTagValueList_t)); +void eip712_format_hash(uint8_t index) { + g_pairs[index].item = "Domain hash"; + g_pairs[index].value = format_hash(tmpCtx.messageSigningContext712.domainHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 0); + index++; + g_pairs[index].item = "Message hash"; + g_pairs[index].value = format_hash(tmpCtx.messageSigningContext712.messageHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 70); +} - if (nbPairs < 2) { - return; // Ensure we have enough space for two pairs +/** + * Initialize EIP712 flow + * + * @param filtering the filtering mode to use for the EIP712 flow + * + */ +void ui_712_start(e_eip712_filtering_mode filtering) { + if (appState != APP_STATE_IDLE) { + reset_app_context(); + } + appState = APP_STATE_SIGNING_EIP712; + memset(&strings, 0, sizeof(strings)); + memset(&warning, 0, sizeof(nbgl_warning_t)); + if (filtering == EIP712_FILTERING_BASIC) { + // If the user has requested a filtered view, we will not show the warning + warning.predefinedSet |= SET_BIT(BLIND_SIGNING_WARN); } - pairs[0].item = "Domain hash"; - pairs[0].value = format_hash(tmpCtx.messageSigningContext712.domainHash, - strings.tmp.tmp, - sizeof(strings.tmp.tmp), - 0); - pairs[1].item = "Message hash"; - pairs[1].value = format_hash(tmpCtx.messageSigningContext712.messageHash, - strings.tmp.tmp, - sizeof(strings.tmp.tmp), - 70); - - pairs_list->nbPairs = 2; - pairs_list->pairs = pairs; - pairs_list->nbMaxLinesForValue = 0; } diff --git a/src_features/signMessageEIP712_common/common_712.h b/src_features/signMessageEIP712_common/common_712.h index ff4cc6020..4c6752741 100644 --- a/src_features/signMessageEIP712_common/common_712.h +++ b/src_features/signMessageEIP712_common/common_712.h @@ -1,12 +1,11 @@ #pragma once #include -#include "ux.h" -#include "nbgl_use_case.h" +#include "ui_logic.h" -void eip712_format_hash(nbgl_contentTagValue_t *pairs, - uint8_t nbPairs, - nbgl_contentTagValueList_t *pairs_list); +void ui_712_start(e_eip712_filtering_mode filtering); -unsigned int ui_712_approve_cb(); -unsigned int ui_712_reject_cb(); +void eip712_format_hash(uint8_t index); + +void ui_712_approve_cb(void); +void ui_712_reject_cb(void); diff --git a/src_features/signTx/cmd_signTx.c b/src_features/signTx/cmd_signTx.c index b23f9bcf5..dc01ff76f 100644 --- a/src_features/signTx/cmd_signTx.c +++ b/src_features/signTx/cmd_signTx.c @@ -4,11 +4,11 @@ #include "eth_plugin_interface.h" #include "apdu_constants.h" #include "swap_error_code_helpers.h" -#include "gtp_tx_info.h" #include "common_ui.h" #include "ui_callbacks.h" #include "mem.h" #include "mem_utils.h" +#include "tx_ctx.h" typedef enum { SIGN_MODE_BASIC = 0, @@ -147,6 +147,10 @@ uint16_t handleSign(uint8_t p1, PRINTF("Error: instructions hash mismatch!\n"); return APDU_RESPONSE_INVALID_DATA; } + if (get_tx_ctx_count() != 1) { + PRINTF("Error: remnant unprocessed TX context!\n"); + return APDU_RESPONSE_CONDITION_NOT_SATISFIED; + } if (!ui_gcs()) { return APDU_RESPONSE_INTERNAL_ERROR; } @@ -169,6 +173,9 @@ uint16_t handleSign(uint8_t p1, } } if (sw != APDU_NO_RESPONSE) { + if ((sw != APDU_RESPONSE_OK) && (g_tx_hash_ctx != NULL)) { + mem_buffer_cleanup((void **) &g_tx_hash_ctx); + } return sw; } diff --git a/src_features/signTx/ethUstream.c b/src_features/signTx/ethUstream.c index f7a6da26c..020d8193d 100644 --- a/src_features/signTx/ethUstream.c +++ b/src_features/signTx/ethUstream.c @@ -23,6 +23,10 @@ #include "common_utils.h" #include "feature_signTx.h" #include "calldata.h" +#include "tx_ctx.h" // g_parked_calldata +#include "utils.h" +#include "shared_context.h" // tmpContent +#include "read.h" // read_u64_be static bool check_fields(txContext_t *context, const char *name, uint32_t length) { UNUSED(name); // Just for the case where DEBUG is not enabled @@ -296,6 +300,8 @@ static bool processTo(txContext_t *context) { } static bool processData(txContext_t *context) { + uint32_t offset = 0; + PRINTF("PROCESS DATA\n"); if (check_fields(context, "RLP_DATA", 0) == false) { return false; @@ -310,17 +316,54 @@ static bool processData(txContext_t *context) { } if (context->store_calldata) { if (context->currentFieldPos == 0) { - if (!calldata_init(context->currentFieldLength)) { + if (copySize < 4) { + PRINTF("Was about to initialize a calldata without a complete selector (%u)!\n", + copySize); + return false; + } + offset = CALLDATA_SELECTOR_SIZE; + if ((g_parked_calldata = calldata_init(context->currentFieldLength - offset, + context->workBuffer)) == NULL) { return false; } } - calldata_append(context->workBuffer, copySize); + if (!calldata_append(g_parked_calldata, + context->workBuffer + offset, + copySize - offset)) + return false; } if (copyTxData(context, NULL, copySize) == false) { return false; } } if (context->currentFieldPos == context->currentFieldLength) { + if (context->store_calldata) { + uint8_t to[ADDRESS_LENGTH]; + uint8_t amount[INT256_LENGTH]; + uint64_t chain_id; + uint8_t chain_id_buf[sizeof(chain_id)]; + + buf_shrink_expand(tmpContent.txContent.destination, + tmpContent.txContent.destinationLength, + to, + sizeof(to)); + buf_shrink_expand(tmpContent.txContent.value.value, + tmpContent.txContent.value.length, + amount, + sizeof(amount)); + buf_shrink_expand(tmpContent.txContent.chainID.value, + tmpContent.txContent.chainID.length, + chain_id_buf, + sizeof(chain_id_buf)); + chain_id = read_u64_be(chain_id_buf, 0); + + if (!tx_ctx_init(g_parked_calldata, NULL, to, amount, &chain_id)) { + calldata_delete(g_parked_calldata); + g_parked_calldata = NULL; + return false; + } + g_parked_calldata = NULL; + } PRINTF("incrementing field\n"); context->currentField++; context->processingField = false; diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 0948f58df..f0e5b0d9a 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -17,6 +17,7 @@ #include "getPublicKey.h" #include "mem.h" #include "mem_utils.h" +#include "tx_ctx.h" static bool g_use_standard_ui; @@ -589,7 +590,8 @@ uint16_t finalize_parsing(const txContext_t *context) { return sw; } if (context->store_calldata) { - if (calldata_get_selector() == NULL) { + if ((get_current_calldata() == NULL) || + (calldata_get_selector(get_current_calldata()) == NULL)) { PRINTF("Asked to store calldata but none was provided!\n"); return APDU_RESPONSE_INVALID_DATA; } diff --git a/src_nbgl/ui_approve_tx.c b/src_nbgl/ui_approve_tx.c index fb50a4641..ddc2eeb15 100644 --- a/src_nbgl/ui_approve_tx.c +++ b/src_nbgl/ui_approve_tx.c @@ -360,7 +360,7 @@ void ux_approve_tx(bool fromPlugin) { warning.predefinedSet |= SET_BIT(BLIND_SIGNING_WARN); } #ifdef HAVE_TRANSACTION_CHECKS - set_tx_simulation_warning(&warning, true, true); + set_tx_simulation_warning(); #endif tx_check_str = ui_tx_simulation_finish_str(); diff --git a/src_nbgl/ui_gcs.c b/src_nbgl/ui_gcs.c index 5b0297c4a..df7ebc323 100644 --- a/src_nbgl/ui_gcs.c +++ b/src_nbgl/ui_gcs.c @@ -12,6 +12,8 @@ #include "ui_utils.h" #include "enum_value.h" #include "proxy_info.h" +#include "trusted_name.h" +#include "tx_ctx.h" static void review_choice(bool confirm) { if (confirm) { @@ -110,7 +112,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { explicit_bzero(keys, sizeof(*values) * MAX_INFO_COUNT); infos->infoContents = values; - if ((value = get_creator_legal_name()) != NULL) { + if ((value = get_creator_legal_name(get_current_tx_info())) != NULL) { snprintf(tmp_buf, tmp_buf_size, #ifdef SCREEN_SIZE_WALLET @@ -123,7 +125,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { return false; } snprintf(tmp_buf, tmp_buf_size, "%s", value); - if ((value = get_creator_url()) != NULL) { + if ((value = get_creator_url(get_current_tx_info())) != NULL) { off = strlen(tmp_buf); snprintf(tmp_buf + off, tmp_buf_size - off, "\n%s", value); } @@ -133,7 +135,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { count += 1; } - if ((value = get_contract_name()) != NULL) { + if ((value = get_contract_name(get_current_tx_info())) != NULL) { snprintf(tmp_buf, tmp_buf_size, #ifdef SCREEN_SIZE_WALLET @@ -156,7 +158,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { } #ifndef SCREEN_SIZE_WALLET - if (!getEthDisplayableAddress((uint8_t *) get_contract_addr(), + if (!getEthDisplayableAddress((uint8_t *) get_contract_addr(get_current_tx_info()), tmp_buf, tmp_buf_size, chainConfig->chainId)) { @@ -171,7 +173,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { count += 1; #endif - if ((value = get_deploy_date()) != NULL) { + if ((value = get_deploy_date(get_current_tx_info())) != NULL) { snprintf(tmp_buf, tmp_buf_size, "Deployed on"); if ((keys[count] = app_mem_strdup(tmp_buf)) == NULL) { return false; @@ -192,7 +194,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { infos->infoExtensions = extensions; infos->withExtensions = true; - if (!getEthDisplayableAddress((uint8_t *) get_contract_addr(), + if (!getEthDisplayableAddress((uint8_t *) get_contract_addr(get_current_tx_info()), tmp_buf, tmp_buf_size, chainConfig->chainId)) { @@ -226,8 +228,7 @@ static bool prepare_infos(nbgl_contentInfoList_t *infos) { } void ui_gcs_cleanup(void) { - mem_buffer_cleanup((void **) &g_trusted_name); - mem_buffer_cleanup((void **) &g_trusted_name_info); + trusted_name_cleanup(); if ((g_pairsList != NULL) && (g_pairsList->pairs != NULL)) { for (int i = 0; i < g_pairsList->nbPairs; ++i) { free_pair(g_pairsList, i); @@ -249,10 +250,13 @@ bool ui_gcs(void) { explicit_bzero(&warning, sizeof(nbgl_warning_t)); #ifdef HAVE_TRANSACTION_CHECKS - set_tx_simulation_warning(&warning, true, true); + set_tx_simulation_warning(); #endif - snprintf(tmp_buf, tmp_buf_size, "Review transaction to %s", get_operation_type()); + snprintf(tmp_buf, + tmp_buf_size, + "Review transaction to %s", + get_operation_type(get_current_tx_info())); if ((g_titleMsg = app_mem_strdup(tmp_buf)) == NULL) { ui_gcs_cleanup(); return false; @@ -262,7 +266,7 @@ bool ui_gcs(void) { tmp_buf_size, "%s transaction to %s?", ui_tx_simulation_finish_str(), - get_operation_type()); + get_operation_type(get_current_tx_info())); #else snprintf(tmp_buf, tmp_buf_size, "%s transaction", ui_tx_simulation_finish_str()); #endif @@ -288,7 +292,7 @@ bool ui_gcs(void) { } g_pairs[0].item = app_mem_strdup("Interaction with"); - g_pairs[0].value = get_creator_name(); + g_pairs[0].value = get_creator_name(get_current_tx_info()); if (g_pairs[0].value == NULL) { // not great, but this cannot be NULL g_pairs[0].value = app_mem_strdup("a smart contract"); @@ -314,7 +318,7 @@ bool ui_gcs(void) { return false; } ext->aliasType = INFO_LIST_ALIAS; - if ((ext->backText = get_creator_name()) == NULL) { + if ((ext->backText = get_creator_name(get_current_tx_info())) == NULL) { ext->backText = app_mem_strdup("Smart contract information"); } else { ext->backText = app_mem_strdup(ext->backText); diff --git a/src_nbgl/ui_message_signing.c b/src_nbgl/ui_message_signing.c index a67f86a59..59ce34894 100644 --- a/src_nbgl/ui_message_signing.c +++ b/src_nbgl/ui_message_signing.c @@ -1,11 +1,14 @@ #include "ui_nbgl.h" #include "ui_logic.h" #include "common_712.h" +#include "common_ui.h" #include "ui_utils.h" +#include "trusted_name.h" +#include "proxy_info.h" static void ui_typed_message_review_choice_common(bool confirm, - unsigned int (*approve_func)(), - unsigned int (*reject_func)()) { + nbgl_callback_t approve_func, + nbgl_callback_t reject_func) { if (confirm) { approve_func(); nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_SIGNED, ui_idle); @@ -14,6 +17,8 @@ static void ui_typed_message_review_choice_common(bool confirm, nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_REJECTED, ui_idle); } ui_all_cleanup(); + trusted_name_cleanup(); + proxy_cleanup(); } void ui_typed_message_review_choice_v0(bool confirm) { diff --git a/src_nbgl/ui_nbgl.h b/src_nbgl/ui_nbgl.h index 1a0b59027..5789c22e4 100644 --- a/src_nbgl/ui_nbgl.h +++ b/src_nbgl/ui_nbgl.h @@ -5,11 +5,11 @@ #include "glyphs.h" #ifdef SCREEN_SIZE_WALLET -#define ICON_APP_WARNING C_Warning_64px -#define ICON_APP_REVIEW C_Review_64px +#define ICON_APP_WARNING LARGE_WARNING_ICON +#define ICON_APP_REVIEW LARGE_REVIEW_ICON #else -#define ICON_APP_WARNING C_icon_warning -#define ICON_APP_REVIEW C_icon_certificate +#define ICON_APP_WARNING WARNING_ICON +#define ICON_APP_REVIEW REVIEW_ICON #endif const nbgl_icon_details_t* get_app_icon(bool caller_icon); diff --git a/src_nbgl/ui_safe_account.c b/src_nbgl/ui_safe_account.c new file mode 100644 index 000000000..45860c1f1 --- /dev/null +++ b/src_nbgl/ui_safe_account.c @@ -0,0 +1,211 @@ +#ifdef HAVE_SAFE_ACCOUNT +#include "cmd_safe_account.h" +#include "safe_descriptor.h" +#include "signer_descriptor.h" +#include "apdu_constants.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" +#include "ui_utils.h" +#include "mem_utils.h" + +#define MAX_PAIRS 2 +#define TAG_MAX_LEN 10 +#define ADDRESS_LENGTH_STR ((ADDRESS_LENGTH * 2) + 3) // "0x" + 2 * ADDRESS_LENGTH + '\0' + +// Structure to manage dynamic string arrays +typedef struct { + char **pointers; // Array of string pointers + char *buffer; // Buffer containing all string data +} string_array_t; + +// Structure to manage tag-value g_pairs +typedef struct { + string_array_t tags; // Tags/labels + string_array_t values; // Corresponding values +} tag_value_collection_t; + +static tag_value_collection_t *signersInfo = NULL; +static nbgl_contentValueExt_t *extensions = NULL; +static nbgl_contentTagValue_t *tagValuePairs = NULL; +static nbgl_contentTagValueList_t *tagValueList = NULL; + +/** + * @brief Cleanup the memory buffers and reset the Safe Account state. + * + * @param[in] sw Status word to send back to the host. + */ +static void _cleanup(uint16_t sw) { + ui_pairs_cleanup(); + mem_buffer_cleanup((void **) &extensions); + mem_buffer_cleanup((void **) &tagValuePairs); + mem_buffer_cleanup((void **) &tagValueList); + if (signersInfo != NULL) { + mem_buffer_cleanup((void **) &signersInfo->tags.buffer); + mem_buffer_cleanup((void **) &signersInfo->tags.pointers); + mem_buffer_cleanup((void **) &signersInfo->values.buffer); + mem_buffer_cleanup((void **) &signersInfo->values.pointers); + mem_buffer_cleanup((void **) &signersInfo); + } + clear_safe_account(); + io_seproxyhal_send_status(sw, 0, true, false); +} + +/** + * @brief Prepare the memory buffers for displaying the Safe Account information. + * + * @return whether it was successful + */ +static bool _prepare_memory(void) { + uint16_t totalSize = 0; + // Init the g_pairs structure + if (ui_pairs_init(MAX_PAIRS) == false) { + return false; + } + + // Allocate memory for extensions to display Safe Address QRCode and Signers Addressss + if (mem_buffer_allocate((void **) &extensions, sizeof(nbgl_contentValueExt_t) * 2) == false) { + return false; + } + if (mem_buffer_allocate((void **) &tagValueList, sizeof(nbgl_contentTagValueList_t)) == false) { + return false; + } + if (mem_buffer_allocate((void **) &tagValuePairs, + sizeof(nbgl_contentTagValue_t) * SAFE_DESC->signers_count) == false) { + return false; + } + + // Allocate pointers array for Signers tags/values + if (mem_buffer_allocate((void **) &signersInfo, sizeof(tag_value_collection_t)) == false) { + return false; + } + + // Allocate pointers array for tags + if (mem_buffer_allocate((void **) &signersInfo->tags.pointers, + sizeof(char *) * SAFE_DESC->signers_count) == false) { + return false; + } + + // Allocate buffer for actual tag strings + totalSize = SAFE_DESC->signers_count * (TAG_MAX_LEN + 1); + if (mem_buffer_allocate((void **) &signersInfo->tags.buffer, totalSize) == false) { + return false; + } + + // Allocate pointers array for values + if (mem_buffer_allocate((void **) &signersInfo->values.pointers, + sizeof(char *) * SAFE_DESC->signers_count) == false) { + return false; + } + + // Allocate buffer for actual value strings + totalSize = SAFE_DESC->signers_count * (ADDRESS_LENGTH_STR + 1); + if (mem_buffer_allocate((void **) &signersInfo->values.buffer, totalSize) == false) { + return false; + } + explicit_bzero((void *) &strings, sizeof(strings_t)); + return true; +} + +/** + * @brief Prepare the strings for display in the Safe Account UI. + * + */ +static void _prepare_strings(void) { + uint16_t i = 0; + char *ptr = NULL; + // Prepare the strings for display + array_bytes_string(strings.tmp.tmp, ADDRESS_LENGTH_STR, SAFE_DESC->address, ADDRESS_LENGTH); + snprintf(strings.tmp.tmp + ADDRESS_LENGTH_STR, + sizeof(strings.tmp.tmp) - ADDRESS_LENGTH_STR, + "%d out of %d", + SAFE_DESC->threshold, + SAFE_DESC->signers_count); + // Prepare the signers information + // Populate tag strings + ptr = signersInfo->tags.buffer; + for (i = 0; i < SAFE_DESC->signers_count; i++) { + snprintf(ptr, TAG_MAX_LEN, "Signer %d", i + 1); + signersInfo->tags.pointers[i] = ptr; + ptr += TAG_MAX_LEN + 1; + } + + // Populate value strings + ptr = signersInfo->values.buffer; + for (i = 0; i < SAFE_DESC->signers_count; i++) { + array_bytes_string(ptr, ADDRESS_LENGTH_STR, SIGNER_DESC.data[i].address, ADDRESS_LENGTH); + signersInfo->values.pointers[i] = ptr; + ptr += ADDRESS_LENGTH_STR + 1; + } +} + +/** + * @brief Set the tag value g_pairs for the Safe Account information. + * + */ +static void setTagValuePairs(void) { + uint8_t nbPairs = 0; + uint16_t i = 0; + + g_pairs[nbPairs].item = "Your role"; + g_pairs[nbPairs].value = ROLE_STR(SAFE_DESC->role); + + nbPairs++; + g_pairs[nbPairs].item = "Threshold"; + g_pairs[nbPairs].value = strings.tmp.tmp + ADDRESS_LENGTH_STR; + g_pairs[nbPairs].aliasValue = 1; + g_pairs[nbPairs].extension = &extensions[1]; + extensions[1].aliasType = TAG_VALUE_LIST_ALIAS; + extensions[1].title = ""; + extensions[1].tagValuelist = tagValueList; + tagValueList->pairs = tagValuePairs; + tagValueList->nbPairs = SAFE_DESC->signers_count; + for (i = 0; i < SAFE_DESC->signers_count; i++) { + tagValuePairs[i].item = signersInfo->tags.pointers[i]; + tagValuePairs[i].value = signersInfo->values.pointers[i]; + } +} + +/** + * @brief Callback for the Safe Account review. + * + * @param[in] confirm Flag indicating whether the user confirmed the Safe Account + */ +static void review_cb(bool confirm) { + if (confirm) { + // User confirmed the Safe Account + _cleanup(APDU_RESPONSE_OK); + nbgl_useCaseStatus("Safe Address validated", true, ui_idle); + return; + } else { + // User rejected the Safe Account + _cleanup(APDU_RESPONSE_CONDITION_NOT_SATISFIED); + nbgl_useCaseStatus("Safe Address rejected", false, ui_idle); + } +} + +/** + * @brief Display the Safe Account information in a review screen. + * + */ +void ui_display_safe_account(void) { + // Memory allocations + if (_prepare_memory() == false) { + // Memory allocation failed in _prepare_memory + _cleanup(APDU_RESPONSE_INSUFFICIENT_MEMORY); + return; + } + // Prepare strings for display + _prepare_strings(); + + // Setup data to display + setTagValuePairs(); + + nbgl_useCaseAddressReview(strings.tmp.tmp, + g_pairsList, + &C_multisig, + "Verify Safe address", + NULL, + review_cb); +} + +#endif // HAVE_SAFE_ACCOUNT diff --git a/src_nbgl/ui_sign_712.c b/src_nbgl/ui_sign_712.c index bfc934d66..49448c118 100644 --- a/src_nbgl/ui_sign_712.c +++ b/src_nbgl/ui_sign_712.c @@ -1,204 +1,76 @@ +#include "apdu_constants.h" #include "common_ui.h" #include "common_712.h" #include "ui_nbgl.h" -#include "ui_logic.h" #include "ui_message_signing.h" #include "cmd_get_tx_simulation.h" -#include "utils.h" #include "ui_utils.h" +#include "mem_utils.h" +/** + * Trigger the EIP712 review flow + * + * @param operationType the type of operation to review + * @param choiceCallback the callback to call when the user makes a choice + * + */ +static void ui_712_start_review(nbgl_operationType_t operationType, + nbgl_choiceCallback_t choiceCallback) { #ifdef SCREEN_SIZE_WALLET -#define PAIR_COUNT 7 -#else -#define PAIR_COUNT 2 -#endif - -static uint8_t pair_idx; -static bool review_skipped; -static bool hash_displayed; - -static nbgl_callback_t skip_callback = NULL; - -static void message_progress(bool confirm) { - if (!review_skipped) { -#ifdef SCREEN_SIZE_WALLET - if (g_pairsList->nbPairs < pair_idx) { - ui_712_delete_pairs(pair_idx - g_pairsList->nbPairs); - const s_ui_712_pair *tmp = ui_712_get_pairs(); - if (tmp != NULL) { - g_pairs[0].item = tmp->key; - g_pairs[0].value = tmp->value; - } - pair_idx = pair_idx - g_pairsList->nbPairs; - } -#else - ui_712_delete_pairs(0); - pair_idx = 0; -#endif - } - if (confirm) { - if (ui_712_next_field() == EIP712_NO_MORE_FIELD) { - ui_712_switch_to_sign(); - } - } else { - ui_typed_message_review_choice(false); - } -} - -#ifdef SCREEN_SIZE_WALLET -static void review_skip(void) { - review_skipped = true; - message_progress(true); -} -#endif // SCREEN_SIZE_WALLET - -static void message_update(bool confirm) { - bool flag; - bool skippable; - - if (confirm) { - if (!review_skipped) { - LEDGER_ASSERT(ui_712_push_new_pair(strings.tmp.tmp2, strings.tmp.tmp), "Out of memory"); - const s_ui_712_pair *tmp; - for (tmp = ui_712_get_pairs(); (s_ui_712_pair *) ((s_flist_node *) tmp)->next != NULL; - tmp = (s_ui_712_pair *) ((s_flist_node *) tmp)->next) - ; - if (tmp != NULL) { - g_pairs[pair_idx].item = tmp->key; - g_pairs[pair_idx].value = tmp->value; - pair_idx += 1; - } - skippable = warning.predefinedSet & SET_BIT(BLIND_SIGNING_WARN); - g_pairsList->nbPairs = - nbgl_useCaseGetNbTagValuesInPageExt(pair_idx, g_pairsList, 0, skippable, &flag); - } -#ifdef SCREEN_SIZE_WALLET - if (!review_skipped && ((pair_idx == PAIR_COUNT) || (g_pairsList->nbPairs < pair_idx))) { + const char *tx_check_str = ui_tx_simulation_finish_str(); + const char *title_suffix = " typed message?"; #else - if (!review_skipped) { + const char *tx_check_str = "Sign"; + const char *title_suffix = " message"; #endif - nbgl_useCaseReviewStreamingContinueExt(g_pairsList, message_progress, skip_callback); - } else { - message_progress(true); - } - } else { - ui_typed_message_review_choice(false); - } -} + uint8_t finish_len = 1; // Initialize lengths to 1 for '\0' character -static void ui_712_start_common(void) { - ui_pairs_init(PAIR_COUNT); - pair_idx = 0; - review_skipped = false; - hash_displayed = false; -#ifdef SCREEN_SIZE_WALLET - skip_callback = review_skip; -#endif // SCREEN_SIZE_WALLET - if (appState != APP_STATE_IDLE) { - reset_app_context(); - } - appState = APP_STATE_SIGNING_EIP712; - explicit_bzero(&warning, sizeof(nbgl_warning_t)); + // Initialize the finish title string + finish_len += strlen(tx_check_str); + finish_len += strlen(title_suffix); + ui_buffers_init(0, 0, finish_len); + snprintf(g_finishMsg, finish_len, "%s%s", tx_check_str, title_suffix); #ifdef HAVE_TRANSACTION_CHECKS - set_tx_simulation_warning(&warning, false, false); + set_tx_simulation_warning(); #endif -} -void ui_712_start_unfiltered(void) { - ui_712_start_common(); - warning.predefinedSet |= SET_BIT(BLIND_SIGNING_WARN); - nbgl_useCaseAdvancedReviewStreamingStart(TYPE_MESSAGE | SKIPPABLE_OPERATION, - &ICON_APP_REVIEW, - "Review typed message", - NULL, - &warning, - message_update); + nbgl_useCaseAdvancedReview(operationType, + g_pairsList, + &ICON_APP_REVIEW, + "Review typed message", + NULL, + g_finishMsg, + NULL, + &warning, + choiceCallback); } -void ui_712_start(void) { - ui_712_start_common(); - if (warning.predefinedSet == 0) { - nbgl_useCaseReviewStreamingStart(TYPE_MESSAGE, - &ICON_APP_REVIEW, - "Review typed message", - NULL, - message_update); - } else { - nbgl_useCaseAdvancedReviewStreamingStart(TYPE_MESSAGE, - &ICON_APP_REVIEW, - "Review typed message", - NULL, - &warning, - message_update); - } -} +/** + * Start EIP712 signature review flow + * + */ +void ui_sign_712(void) { + // Initialize the pairs list + ui_712_push_pairs(); -void ui_712_switch_to_message(void) { - message_update(true); + ui_712_start_review(TYPE_MESSAGE, ui_typed_message_review_choice); } -#ifdef HAVE_TRANSACTION_CHECKS -static void ui_712_tx_check_cb(bool confirm) { - const char *tx_check_str = NULL; -#ifdef SCREEN_SIZE_WALLET - const char *title_suffix = " typed message?"; -#else - const char *title_suffix = " message"; -#endif - uint8_t finish_len = 1; // Initialize lengths to 1 for '\0' character +/** + * Start EIP712 signature review flow in Legacy (v0) mode + * + */ +void ui_sign_712_v0(void) { + ui_712_start(EIP712_FILTERING_BASIC); - if (confirm) { - // User has clicked on "Reject transaction" - ui_typed_message_review_choice(false); - } else { - tx_check_str = ui_tx_simulation_finish_str(); - finish_len += strlen(tx_check_str); - finish_len += strlen(title_suffix); - ui_buffers_init(0, 0, finish_len); - // User has clicked on "Sign anyway" - snprintf(g_finishMsg, finish_len, "%s%s", tx_check_str, title_suffix); - nbgl_useCaseReviewStreamingFinish(g_finishMsg, ui_typed_message_review_choice); + // Initialize the buffers + if (!ui_pairs_init(2)) { + // Initialization failed, cleanup and return + return; } -} -#endif -void ui_712_switch_to_sign(void) { -#ifdef SCREEN_SIZE_WALLET - const char *tx_check_str = ui_tx_simulation_finish_str(); - const char *title_suffix = " typed message?"; -#else - const char *tx_check_str = "Sign"; - const char *title_suffix = " message"; -#endif - uint8_t finish_len = 1; // Initialize lengths to 1 for '\0' character + // Initialize the tag/value pairs + eip712_format_hash(0); - if (!review_skipped && (pair_idx > 0)) { - g_pairsList->nbPairs = pair_idx; - pair_idx = 0; - nbgl_useCaseReviewStreamingContinueExt(g_pairsList, message_progress, skip_callback); - } else { - if (N_storage.displayHash && !hash_displayed) { - // If the hash is not displayed yet, we need to format it and display it - // Prepare the pairs list with the hashes - eip712_format_hash(g_pairs, PAIR_COUNT, g_pairsList); - g_pairs[0].forcePageStart = 1; - hash_displayed = true; - pair_idx = 0; - // Continue with the pairs list but no more skip needed here - nbgl_useCaseReviewStreamingContinue(g_pairsList, message_progress); - return; - } -#ifdef HAVE_TRANSACTION_CHECKS - if ((TX_SIMULATION.risk != RISK_UNKNOWN) && ((check_tx_simulation_hash() == false) || - check_tx_simulation_from_address() == false)) { - ui_tx_simulation_error(ui_712_tx_check_cb); - return; - } -#endif - finish_len += strlen(tx_check_str); - finish_len += strlen(title_suffix); - ui_buffers_init(0, 0, finish_len); - snprintf(g_finishMsg, finish_len, "%s%s", tx_check_str, title_suffix); - nbgl_useCaseReviewStreamingFinish(g_finishMsg, ui_typed_message_review_choice); - } + ui_712_start_review(TYPE_TRANSACTION, ui_typed_message_review_choice_v0); } diff --git a/src_nbgl/ui_sign_712_v0.c b/src_nbgl/ui_sign_712_v0.c deleted file mode 100644 index 3417967b2..000000000 --- a/src_nbgl/ui_sign_712_v0.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "ui_nbgl.h" -#include "common_712.h" -#include "ui_message_signing.h" -#include "cmd_get_tx_simulation.h" -#include "utils.h" -#include "ui_utils.h" - -#define MAX_NB_PAIRS 2 -#define FINISH_MSG_LEN 32 - -void ui_sign_712_v0(void) { - if (appState != APP_STATE_IDLE) { - reset_app_context(); - } - appState = APP_STATE_SIGNING_EIP712; - // Initialize the buffers - if (!ui_pairs_init(MAX_NB_PAIRS)) { - // Initialization failed, cleanup and return - return; - } - // Initialize the buffers - if (!ui_buffers_init(0, 0, FINISH_MSG_LEN)) { - // Initialization failed, cleanup and return - return; - } - - explicit_bzero(&warning, sizeof(nbgl_warning_t)); -#ifdef HAVE_TRANSACTION_CHECKS - set_tx_simulation_warning(&warning, true, true); -#endif - warning.predefinedSet |= SET_BIT(BLIND_SIGNING_WARN); - - // Initialize the g_pairs and g_pairsList structures - eip712_format_hash(g_pairs, MAX_NB_PAIRS, g_pairsList); - - snprintf(g_finishMsg, FINISH_MSG_LEN, "%s typed message?", ui_tx_simulation_finish_str()); - nbgl_useCaseAdvancedReview(TYPE_TRANSACTION, - g_pairsList, - &ICON_APP_REVIEW, - "Review typed message", - NULL, - g_finishMsg, - NULL, - &warning, - ui_typed_message_review_choice_v0); -} diff --git a/src_nbgl/ui_sign_message.c b/src_nbgl/ui_sign_message.c index a6bf7ce63..6c8352e6c 100644 --- a/src_nbgl/ui_sign_message.c +++ b/src_nbgl/ui_sign_message.c @@ -32,7 +32,7 @@ void ui_191_start(const char *message) { explicit_bzero(&warning, sizeof(nbgl_warning_t)); #ifdef HAVE_TRANSACTION_CHECKS - set_tx_simulation_warning(&warning, false, true); + set_tx_simulation_warning(); #endif snprintf(g_finishMsg, diff --git a/src_nbgl/ui_tx_simulation.c b/src_nbgl/ui_tx_simulation.c index accce604b..5070ebddc 100644 --- a/src_nbgl/ui_tx_simulation.c +++ b/src_nbgl/ui_tx_simulation.c @@ -20,24 +20,6 @@ enum { // Global flag to send Opt-In result static bool g_response_expected; -/** - * @brief Display the transaction simulation error popup - * - * @param[in] callback Callback to be called after the user has made a choice - */ -void ui_tx_simulation_error(nbgl_choiceCallback_t callback) { -#ifdef HAVE_PIEZO_SOUND - io_seproxyhal_play_tune(TUNE_NEUTRAL); -#endif // HAVE_PIEZO_SOUND - nbgl_useCaseChoice(&C_Denied_Circle_64px, - "Transaction Check failed because of technical reasons", - "Reject this transaction and try again. " - "If the issue persists, get help at: ledger.com/e9", - "Reject transaction", - "Continue anyway", - callback); -} - /** * @brief Callback called when user press a button on the opt-in explain screen * diff --git a/tests/fuzzing/CMakeLists.txt b/tests/fuzzing/CMakeLists.txt index 0ab0ec455..d6ff1439b 100644 --- a/tests/fuzzing/CMakeLists.txt +++ b/tests/fuzzing/CMakeLists.txt @@ -154,6 +154,7 @@ set(DEFINES STANDARD_APP_SYNC_RAPDU HAVE_SWAP HAVE_TRANSACTION_CHECKS + HAVE_SAFE_ACCOUNT explicit_bzero=bzero # Fix for https://github.com/google/sanitizers/issues/1507 ) @@ -187,6 +188,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/../../src_features/provide_proxy_info/ ${CMAKE_SOURCE_DIR}/../../src_features/provide_tx_simulation/ ${CMAKE_SOURCE_DIR}/../../src_features/signAuthorizationEIP7702/ + ${CMAKE_SOURCE_DIR}/../../src_features/provide_safe_account/ ${CMAKE_SOURCE_DIR}/../../src_nbgl/ ${BOLOS_SDK}/include ${BOLOS_SDK}/target/${TARGET_DEVICE}/include @@ -211,6 +213,7 @@ FILE(GLOB_RECURSE SOURCES ${CMAKE_SOURCE_DIR}/../../src_features/provide_proxy_info/*.c ${CMAKE_SOURCE_DIR}/../../src_features/provide_tx_simulation/*.c ${CMAKE_SOURCE_DIR}/../../src_features/signAuthorizationEIP7702/*.c + ${CMAKE_SOURCE_DIR}/../../src_features/provide_safe_account/*.c ${CMAKE_SOURCE_DIR}/../../src/list.c ${CMAKE_SOURCE_DIR}/../../src_nbgl/ui_utils.c ${CMAKE_SOURCE_DIR}/../../src/mem.c diff --git a/tests/fuzzing/local_run.sh b/tests/fuzzing/local_run.sh index cbc179247..0c02af315 100755 --- a/tests/fuzzing/local_run.sh +++ b/tests/fuzzing/local_run.sh @@ -7,6 +7,11 @@ rm -rf build cmake -B build -S . -DCMAKE_C_COMPILER=/usr/bin/clang -DSANITIZER=address cmake --build build +if ! [ -f ./build/fuzzer ]; then + echo "Build failed, please check the output above." + exit 1 +fi + # Create the corpus directory if it doesn't exist if ! [ -d ./corpus ]; then mkdir corpus @@ -26,7 +31,7 @@ then exit 0 fi -# Remove previous artifcats +# Remove previous artifacts rm default.profdata default.profraw # Run profiling on the corpus diff --git a/tests/fuzzing/src/fuzzer.c b/tests/fuzzing/src/fuzzer.c index 85ef96dd9..bb161ee7c 100644 --- a/tests/fuzzing/src/fuzzer.c +++ b/tests/fuzzing/src/fuzzer.c @@ -20,9 +20,13 @@ #include "auth_7702.h" #include "commands_7702.h" +#include "safe_descriptor.h" +#include "signer_descriptor.h" + #include "shared_context.h" #include "tlv.h" #include "apdu_constants.h" +#include "nbgl_use_case.h" // Fuzzing harness interface typedef int (*harness)(const uint8_t *data, size_t size); @@ -42,6 +46,7 @@ const chain_config_t *chainConfig = &config; uint8_t appState; tmpCtx_t tmpCtx; strings_t strings; +nbgl_warning_t warning; // Mock the storage to enable wanted features const internalStorage_t N_storage_real = { .tx_check_enable = true, @@ -136,19 +141,24 @@ int fuzzTxSimulation(const uint8_t *data, size_t size) { return 0; } +static s_calldata *g_calldata = NULL; + int fuzzCalldata(const uint8_t *data, size_t size) { while (size > 0) { switch (data[0]) { case 'I': data++; size--; - calldata_init(500); + if (g_calldata != NULL) { + calldata_delete(g_calldata); + } + g_calldata = calldata_init(500, NULL); break; case 'W': size--; data++; if (size < 1 || size < data[0] + 1) return 0; - calldata_append(data + 1, data[0]); + calldata_append(g_calldata, data + 1, data[0]); size -= (1 + data[0]); data += 1 + data[0]; break; @@ -156,7 +166,7 @@ int fuzzCalldata(const uint8_t *data, size_t size) { size--; data++; if (size < 1) return 0; - calldata_get_chunk(data[0]); + calldata_get_chunk(g_calldata, data[0]); size--; data++; break; @@ -185,6 +195,14 @@ int fuzzEIP7702(const uint8_t *data, size_t size) { return 0; } +int fuzzSafeCmd(const uint8_t *data, size_t size) { + return handle_safe_tlv_payload(data, size); +} + +int fuzzSignerCmd(const uint8_t *data, size_t size) { + return handle_signer_tlv_payload(data, size); +} + // Array of fuzzing harness functions harness harnesses[] = { fuzzGenericParserFieldCmd, @@ -197,6 +215,8 @@ harness harnesses[] = { fuzzTxSimulation, fuzzCalldata, fuzzEIP7702, + fuzzSafeCmd, + fuzzSignerCmd, }; /* Main fuzzing handler called by libfuzzer */ @@ -211,8 +231,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { explicit_bzero(&sha3, sizeof(sha3)); explicit_bzero(&global_sha3, sizeof(global_sha3)); - calldata_cleanup(); - uint8_t target; txContext.content = &txContent; diff --git a/tests/fuzzing/src/mock.c b/tests/fuzzing/src/mock.c index 90c2b5e27..75326c24c 100644 --- a/tests/fuzzing/src/mock.c +++ b/tests/fuzzing/src/mock.c @@ -230,6 +230,9 @@ void ui_sign_7702_auth(void) { void ui_sign_7702_revocation(void) { } +void ui_display_safe_account(void) { +} + cx_err_t cx_keccak_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size) { UNUSED(size); memset_s(hash, 0, sizeof(cx_sha3_t)); @@ -328,3 +331,24 @@ void mem_free(mem_ctx_t ctx, void *ptr) { (void) ctx; free(ptr); } + +void ui_712_set_title(const char *str, size_t length) { + (void) str; + (void) length; +} + +void ui_712_set_value(const char *str, size_t length) { + (void) str; + (void) length; +} + +typedef void s_eip712_calldata_info; + +s_eip712_calldata_info *get_current_calldata_info(void) { + return NULL; +} + +bool calldata_info_all_received(const s_eip712_calldata_info *calldata_info) { + (void) calldata_info; + return false; +} diff --git a/tests/ragger/abis/safe_1.4.1.abi.json b/tests/ragger/abis/safe_1.4.1.abi.json new file mode 100644 index 000000000..672d6f497 --- /dev/null +++ b/tests/ragger/abis/safe_1.4.1.abi.json @@ -0,0 +1,999 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "AddedOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "approvedHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ApproveHash", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "handler", + "type": "address" + } + ], + "name": "ChangedFallbackHandler", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "guard", + "type": "address" + } + ], + "name": "ChangedGuard", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + } + ], + "name": "ChangedThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "DisabledModule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "EnabledModule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "ExecutionFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ExecutionFromModuleFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ExecutionFromModuleSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "ExecutionSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "RemovedOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "initiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "owners", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "initializer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "fallbackHandler", + "type": "address" + } + ], + "name": "SafeSetup", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "SignMsg", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "addOwnerWithThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hashToApprove", + "type": "bytes32" + } + ], + "name": "approveHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "approvedHashes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "changeThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dataHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "requiredSignatures", + "type": "uint256" + } + ], + "name": "checkNSignatures", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dataHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + } + ], + "name": "checkSignatures", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prevModule", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "disableModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "domainSeparator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "enableModule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "safeTxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasToken", + "type": "address" + }, + { + "internalType": "address", + "name": "refundReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + } + ], + "name": "encodeTransactionData", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "safeTxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasToken", + "type": "address" + }, + { + "internalType": "address payable", + "name": "refundReceiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signatures", + "type": "bytes" + } + ], + "name": "execTransaction", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + } + ], + "name": "execTransactionFromModule", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + } + ], + "name": "execTransactionFromModuleReturnData", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "start", + "type": "address" + }, + { + "internalType": "uint256", + "name": "pageSize", + "type": "uint256" + } + ], + "name": "getModulesPaginated", + "outputs": [ + { + "internalType": "address[]", + "name": "array", + "type": "address[]" + }, + { + "internalType": "address", + "name": "next", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOwners", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "getStorageAt", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Enum.Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "safeTxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasToken", + "type": "address" + }, + { + "internalType": "address", + "name": "refundReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + } + ], + "name": "getTransactionHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "isModuleEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "isOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prevOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "removeOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "handler", + "type": "address" + } + ], + "name": "setFallbackHandler", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guard", + "type": "address" + } + ], + "name": "setGuard", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_owners", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "address", + "name": "fallbackHandler", + "type": "address" + }, + { + "internalType": "address", + "name": "paymentToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "paymentReceiver", + "type": "address" + } + ], + "name": "setup", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "signedMessages", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetContract", + "type": "address" + }, + { + "internalType": "bytes", + "name": "calldataPayload", + "type": "bytes" + } + ], + "name": "simulateAndRevert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prevOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "oldOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "swapOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/tests/ragger/abis/safe_l2_setup_1.4.1.abi.json b/tests/ragger/abis/safe_l2_setup_1.4.1.abi.json new file mode 100644 index 000000000..fb9842cb3 --- /dev/null +++ b/tests/ragger/abis/safe_l2_setup_1.4.1.abi.json @@ -0,0 +1,33 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "singleton", + "type": "address" + } + ], + "name": "ChangedMasterCopy", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l2Singleton", + "type": "address" + } + ], + "name": "setupToL2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/tests/ragger/abis/safe_proxy_factory_1.4.1.abi.json b/tests/ragger/abis/safe_proxy_factory_1.4.1.abi.json new file mode 100644 index 000000000..2b7f221e0 --- /dev/null +++ b/tests/ragger/abis/safe_proxy_factory_1.4.1.abi.json @@ -0,0 +1,139 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract SafeProxy", + "name": "proxy", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "singleton", + "type": "address" + } + ], + "name": "ProxyCreation", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_singleton", + "type": "address" + }, + { + "internalType": "bytes", + "name": "initializer", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + } + ], + "name": "createChainSpecificProxyWithNonce", + "outputs": [ + { + "internalType": "contract SafeProxy", + "name": "proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_singleton", + "type": "address" + }, + { + "internalType": "bytes", + "name": "initializer", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + }, + { + "internalType": "contract IProxyCreationCallback", + "name": "callback", + "type": "address" + } + ], + "name": "createProxyWithCallback", + "outputs": [ + { + "internalType": "contract SafeProxy", + "name": "proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_singleton", + "type": "address" + }, + { + "internalType": "bytes", + "name": "initializer", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "saltNonce", + "type": "uint256" + } + ], + "name": "createProxyWithNonce", + "outputs": [ + { + "internalType": "contract SafeProxy", + "name": "proxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxyCreationCode", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/tests/ragger/dynamic_networks_cfg.py b/tests/ragger/dynamic_networks_cfg.py index 5ee3f4588..cc7f6754f 100644 --- a/tests/ragger/dynamic_networks_cfg.py +++ b/tests/ragger/dynamic_networks_cfg.py @@ -7,7 +7,10 @@ class IconDict(TypedDict): Ticker: str Icon: Dict[DeviceType, str] - +# Icon generation: +# Use the script tools/gen_dynamic_network.py like: +# BOLOS_SDK=/opt/ledger-secure-sdk tools/gen_dynamic_network.py -i glyphs/chain_3_64px.gif -v +# Using '-v' is important, because it displays the image_data value # pylint: disable=line-too-long DYNAMIC_ICONS: Dict[int, IconDict] = { 3: { @@ -16,6 +19,7 @@ class IconDict(TypedDict): "Icon": { DeviceType.NANOX: "", # noqa: E501 DeviceType.FLEX: "4000400021bd0100bb011f8b08000000000002ffed94bf4bc34014c7ff8643514441f2829b20e405a50e0eed26d242dd2df40f30505b6d3bb8ba74b260373b38386670a85b978274ea1f211d9cb228356df079975c9aa44db22bfd4ec97d8ef7e37bf78e68a57fa469894629f8a7b845032b99df2b8c2699443c00851994bb4dc06300c676a8adc797606b82afd327c66698654170d67710f331a5973956383fa073d4bb4bbc0d926fd23be291b5543a78e119b36c443c8be20904bc4439be2192c1ce821f9eb16d7ae25c0f65708a10e26bf4c5399e06bca285c233d67504c74b1fbf0044f82e553094610c0b7c835b28e4d9f8adf958919c8d6c97e385a82d0b4bbce076c833989c776e7c9551aa44de625d1ce46cceaf38d25415d1926b9e47b6cf6b826a9a7628979ab2bfa1bf4186cfd3b3f86bcc1dec495e14544593dc3f3330b0332f80a7d7bdf0add0f9c826aa08a8e13ebd89e8d1b970f9b59bde70c3f5a317e0c3dd90e518dcee1e17efd7abe710408626416b21899eaa8058e05ff598091035d6787cd3f18d5b1c00e190bac7bb6b260cb770e8847a8da4091e72870cbaeb260e70afa65bd356ca03f1704c76dafbe218a9efcb4a7f4dbf34cf947a00080000", # noqa: E501 + DeviceType.APEX_P: "300030000187000085001f8b08000000000002ffa58eb11185300c43cda5a064048fc262ff2e198d82a36288f07ff1dba44b914348340c808b5748b62cb3f7332471dcc56913e7bf88df421335d3446d668ed669a29f34d1631a80332e23396707e06d124ba0e2d9a4278bdcd46dff301e8d3901a528bf32dfe2a1f7febd3bac62484fabb773014af3a5e320010000", # noqa: E501 }, }, 5: { @@ -24,6 +28,7 @@ class IconDict(TypedDict): "Icon": { DeviceType.NANOX: "", # noqa: E501 DeviceType.FLEX: "400040000195000093001f8b08000000000002ff85ceb10dc4300805d01fb970e9113c4a467346cb288ce092223ace80382b892ef9cd93ac0f0678881c4616d980b4bb99aa0801a5874d844ff695b5d7f6c23ad79058f79c8df7e8c5dc7d9fff13ffc61d71d7bcf32549bcef5672c5a430bb1cd6073f68c3cd3d302cd3feea88f547d6a99eb8e87ecbcdecd255b8f869033cfd932feae0c09000020000", # noqa: E501 + DeviceType.APEX_P: "30003000018a000088001f8b08000000000002ff65cdc109c530080660c5438f19a1a3b8ca1ba4d08ed6513a82470f824f8d87941af89024fe02bc8a3c1dfe00c8ee02a85c9e6e2dc889e1ef80108e38ddd7fdfa73cece9cceecfc4fa1c7ab5148a96ca98ed4f8ad6ec65a3ea4687cad621979c6772c338ecdc3d83d67cb3dd591ca94d21b526897fa0394f0729320010000", # noqa: E501 }, }, 56: { @@ -32,6 +37,7 @@ class IconDict(TypedDict): "Icon": { DeviceType.NANOX: "", # noqa: E501 DeviceType.FLEX: "4000400021ff0100fd011f8b08000000000002ffdd554b6ac330101d61f0225090307861c81d5c0c5d1482afe20b945c293941aed2e05d21e810012d0c42d58c64eb63d7dd475944d14833f3deccbc18f322ebf190c6e8875f32373f016a6314e32000b8e873fb0580dd8c69c1ad32336b6e0f7bba468b6501141e1e288c5be7d47e07a8aa0feba77bc70fc031b7c71e6db422f75f67d9ded20b6d8268a4649317c9fd69857022f21c85f6e790e4a3683f0a61112a214e84274278a5fd005048ccbd243e0e51720d46e08e960189d66d8470a26488c223e57e4e118eb4bff8ba4ca26a288d258121d8712311809652063617ffd0af3b47b96a5089578527b2d98c6f5d7844e70fef14e08bfacfcc44126ea48d4847070297757815e2166a75899acfb712774de2d0617dafc1cec86fbda0539e7488fa8f88f66ea8bf1c42b7dee8ac0f762c5df4fe38dba77ffcfbaff6148663c9aff4b460ee6b7c7e082c2dcd8a9f3ef0639f157bfc62d8ddfa2860a1bef5babe737fa09d6df4874748ece3466b7a25636d99fbafc0fe149ff6ac0b1a33f1d2786958684d2698e64327f39128c0325f8c8ae44ad144088d9fcf667b3edd7c9b68be674e4388541f783e08a9be3cf34152e9fd21d7a795be65eebfad3e76561fa7aeeb2ad4c7665f5fd9795f9f0bb9a9effa2f7d37231748abe08201dbf87ff0e2f843ddf7f378957f4df30b82b2cf8e00080000", # noqa: E501 + DeviceType.APEX_P: "300030000199000097001f8b08000000000002ff7d8fb10dc3300c045f50a1468836101709ecb55c180847539045e40d58ba3223fb5d9bc51714f57f0f3c4efa7907cad76de876aa74df810a2c4006de974ed7f158ea5a05688714847694a471f314119beb30a3eaa70d339dbd5bc9b39b4916b765aae2fb4aadaf73c3575ef2171de8168673b8539878a793845424242dc9d9828dd8ee71fe768babfa20010000", # noqa: E501 }, }, 137: { @@ -40,6 +46,7 @@ class IconDict(TypedDict): "Icon": { DeviceType.NANOX: "", # noqa: E501 DeviceType.FLEX: "400040002188010086011f8b08000000000002ffbd55416ac33010943018422f0e855c42fee01e4b09f94a7a0c3df82b3905440ffd4243a1507ae81b4c1e9047180a2604779d58f6ae7664e8250b0ec613ad7646b3aba6b949fc9a2eee8f105f7bdc14083e653d3e1f4d6f4c82f0ed809b3780e70c5f6ab8a6cf8f1b474175a41a2f8db1d7b47b7a3b2276c9506881d8cd87d7bb10afd8a2356048ec12bfe90130cc59d12d9585166f05ffdcb363295b863f21bb54662bfe85cb8ca522402bec2a92ad8d336936e9b50416e19a55e000f837d2d2a2e3f79a7d39f78aec938eb9bf549ae91378fa16a118ca982ea3febe46aa18ca90f59c14ce1c21fbd3c744e087cc582a921e7bf9552a4a761fb1461f39c5114f75f1b9732f5117499f484f813ec84386416f6f75a30b17689fd519ef3cd6f3b83114c300a7dd66b129a276d3a3a3d20209cdc09ce1fac039c50480738e09b8471dc116c18e1a18d6784eb7453bb773ee19cff9d29b37c3f744cdfc0dedc7ee0968dff7487fe97b0acf8bf3c3b48be236f772f307b129c97400080000", # noqa: E501 + DeviceType.APEX_P: "3000300002960000f0f0f0f0f0f0f03df0f04ff0f02f02f0f01f02f0ff04f0d695f0d5a6f0b6b6f0a5c6f096d6f076f5f076f6f065f016f066f6f075e6f086d6f096c5f0a6f0f0d6f0f0d6f0f0cf0df06f0df05f0df06f0df0f0c6f0f0d6f0f0d6f0a5c6f096d6f085f5f076f6f065f025f066f6f075f5f086d6f095d5f0a6b6f0b6a5f0d596f0df04f0ff02f0f01f02f0f02ff0f04df0f0f0f0f0f0f030", # noqa: E501 }, }, } @@ -56,6 +63,9 @@ def get_network_config(dev_type: DeviceType, chain_id: Optional[int] = None) -> elif dev_type == DeviceType.STAX: # Same icons dev_type = DeviceType.FLEX + elif dev_type == DeviceType.APEX_M: + # Same icons + dev_type = DeviceType.APEX_P icon = bytes.fromhex(DYNAMIC_ICONS[chain_id]["Icon"][dev_type]) else: # If no chain_id is found, return empty values diff --git a/tests/ragger/eip712_input_files/safe.json b/tests/ragger/eip712_input_files/safe.json new file mode 100644 index 000000000..968d49d2d --- /dev/null +++ b/tests/ragger/eip712_input_files/safe.json @@ -0,0 +1,73 @@ +{ + "domain": { + "verifyingContract": "0xc1897a9acbdd54028da5f7b76b5833a91553aaf6", + "chainId": 1 + }, + "message": { + "to": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "value": "0", + "data": "0xa9059cbb00000000000000000000000023f8abfc2824c397ccb3da89ae772984107ddb99000000000000000000000000000000000000000000000000000000000083ed02", + "operation": 0, + "baseGas": "0", + "gasPrice": "0", + "gasToken": "0x0000000000000000000000000000000000000000", + "refundReceiver": "0x0000000000000000000000000000000000000000", + "nonce": 1, + "safeTxGas": "0" + }, + "primaryType": "SafeTx", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "SafeTx": [ + { + "type": "address", + "name": "to" + }, + { + "type": "uint256", + "name": "value" + }, + { + "type": "bytes", + "name": "data" + }, + { + "type": "uint8", + "name": "operation" + }, + { + "type": "uint256", + "name": "safeTxGas" + }, + { + "type": "uint256", + "name": "baseGas" + }, + { + "type": "uint256", + "name": "gasPrice" + }, + { + "type": "address", + "name": "gasToken" + }, + { + "type": "address", + "name": "refundReceiver" + }, + { + "type": "uint256", + "name": "nonce" + } + ] + } +} diff --git a/tests/ragger/eip712_input_files/safe_empty.json b/tests/ragger/eip712_input_files/safe_empty.json new file mode 100644 index 000000000..baeba8397 --- /dev/null +++ b/tests/ragger/eip712_input_files/safe_empty.json @@ -0,0 +1,73 @@ +{ + "domain": { + "verifyingContract": "0xc1897a9acbdd54028da5f7b76b5833a91553aaf6", + "chainId": 1 + }, + "message": { + "to": "0x23f8abfc2824c397ccb3da89ae772984107ddb99", + "value": "4200000000000000", + "data": "0x", + "operation": 0, + "baseGas": "0", + "gasPrice": "0", + "gasToken": "0x0000000000000000000000000000000000000000", + "refundReceiver": "0x0000000000000000000000000000000000000000", + "nonce": 2, + "safeTxGas": "0" + }, + "primaryType": "SafeTx", + "types": { + "EIP712Domain": [ + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "SafeTx": [ + { + "type": "address", + "name": "to" + }, + { + "type": "uint256", + "name": "value" + }, + { + "type": "bytes", + "name": "data" + }, + { + "type": "uint8", + "name": "operation" + }, + { + "type": "uint256", + "name": "safeTxGas" + }, + { + "type": "uint256", + "name": "baseGas" + }, + { + "type": "uint256", + "name": "gasPrice" + }, + { + "type": "address", + "name": "gasToken" + }, + { + "type": "address", + "name": "refundReceiver" + }, + { + "type": "uint256", + "name": "nonce" + } + ] + } +} diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign/00000.png new file mode 100644 index 000000000..0418b7642 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign/00001.png b/tests/ragger/snapshots/apex_p/test_blind_sign/00001.png new file mode 100644 index 000000000..68627c2ef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign/00002.png b/tests/ragger/snapshots/apex_p/test_blind_sign/00002.png new file mode 100644 index 000000000..315705fde Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign/00003.png b/tests/ragger/snapshots/apex_p/test_blind_sign/00003.png new file mode 100644 index 000000000..148e6b5a1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign/00004.png b/tests/ragger/snapshots/apex_p/test_blind_sign/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign/00005.png b/tests/ragger/snapshots/apex_p/test_blind_sign/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign/warning/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign/warning/00000.png new file mode 100644 index 000000000..eb1e09fcd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00000.png new file mode 100644 index 000000000..0418b7642 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00001.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00001.png new file mode 100644 index 000000000..36b075f5a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00002.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00002.png new file mode 100644 index 000000000..454dd78e0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00003.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00003.png new file mode 100644 index 000000000..148e6b5a1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00004.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00005.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/warning/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/warning/00000.png new file mode 100644 index 000000000..eb1e09fcd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonce_nonzero/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00000.png new file mode 100644 index 000000000..0418b7642 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00001.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00001.png new file mode 100644 index 000000000..36b075f5a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00002.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00002.png new file mode 100644 index 000000000..5d7629d0c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00003.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00003.png new file mode 100644 index 000000000..148e6b5a1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00004.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00005.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/warning/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/warning/00000.png new file mode 100644 index 000000000..eb1e09fcd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_nonzero/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_not_enabled_error/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign_not_enabled_error/00000.png new file mode 100644 index 000000000..c1ab915bb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_not_enabled_error/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_not_enabled_error/00001.png b/tests/ragger/snapshots/apex_p/test_blind_sign_not_enabled_error/00001.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_not_enabled_error/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00000.png new file mode 100644 index 000000000..0418b7642 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00001.png b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00001.png new file mode 100644 index 000000000..68627c2ef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00002.png b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00002.png new file mode 100644 index 000000000..315705fde Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00003.png b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00003.png new file mode 100644 index 000000000..148e6b5a1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00004.png b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00004.png new file mode 100644 index 000000000..cf109394f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00005.png b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00005.png new file mode 100644 index 000000000..1d65a5392 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00006.png b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/warning/00000.png b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/warning/00000.png new file mode 100644 index 000000000..eb1e09fcd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_blind_sign_rejected/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_clone_thundercore/00000.png b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00000.png new file mode 100644 index 000000000..2fd278824 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_clone_thundercore/00001.png b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00001.png new file mode 100644 index 000000000..9d0b22ace Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_clone_thundercore/00002.png b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00002.png new file mode 100644 index 000000000..38186e55c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_clone_thundercore/00003.png b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00003.png new file mode 100644 index 000000000..18c286070 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_clone_thundercore/00004.png b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_clone_thundercore/00005.png b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00005.png new file mode 100644 index 000000000..f6a0e049e Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_clone_thundercore/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00000.png new file mode 100644 index 000000000..ebdae6724 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00001.png new file mode 100644 index 000000000..391dd40c2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00002.png new file mode 100644 index 000000000..08486effa Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00003.png new file mode 100644 index 000000000..183193cd3 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00004.png new file mode 100644 index 000000000..c8bb8d6a5 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00005.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00005.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00006.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering-verbose/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00000.png new file mode 100644 index 000000000..ce2c5f7d1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00001.png new file mode 100644 index 000000000..abd415e06 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00002.png new file mode 100644 index 000000000..76ea8e146 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00003.png new file mode 100644 index 000000000..2687a8b7d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00004.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00005.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00001.png new file mode 100644 index 000000000..5eb47b330 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_permit/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00001.png new file mode 100644 index 000000000..61cd32967 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_filtering_unlimited/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00001.png new file mode 100644 index 000000000..192697598 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-False-True/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00001.png new file mode 100644 index 000000000..36b18f360 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_missing_token-True-False/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00001.png new file mode 100644 index 000000000..fa9d84a92 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png new file mode 100644 index 000000000..fa9d84a92 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00001.png new file mode 100644 index 000000000..28397fe17 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png new file mode 100644 index 000000000..fa9d84a92 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00001.png new file mode 100644 index 000000000..28397fe17 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png new file mode 100644 index 000000000..1df610d76 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00001.png new file mode 100644 index 000000000..1df610d76 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png new file mode 100644 index 000000000..1df610d76 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00001.png new file mode 100644 index 000000000..6ae3191bb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00000.png new file mode 100644 index 000000000..ce2c5f7d1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00001.png new file mode 100644 index 000000000..46419cf27 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00002.png new file mode 100644 index 000000000..679209482 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00003.png new file mode 100644 index 000000000..2687a8b7d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00004.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00005.png b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_calldata_empty_send/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00000.png b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00000.png new file mode 100644 index 000000000..e2ea03450 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00001.png b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00001.png new file mode 100644 index 000000000..2fd3dc0da Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00002.png b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00002.png new file mode 100644 index 000000000..ebfba54d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00003.png b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00004.png b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip712_filtering_empty_array/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00000.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00000.png new file mode 100644 index 000000000..af780c871 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00001.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00001.png new file mode 100644 index 000000000..2fa832b34 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00002.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00002.png new file mode 100644 index 000000000..3fb69ef06 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00003.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00003.png new file mode 100644 index 000000000..0715daaae Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00004.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00000.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00000.png new file mode 100644 index 000000000..af780c871 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00001.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00001.png new file mode 100644 index 000000000..189086000 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00002.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00002.png new file mode 100644 index 000000000..3fb69ef06 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00003.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00003.png new file mode 100644 index 000000000..0715daaae Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00004.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_param/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00000.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00000.png new file mode 100644 index 000000000..af780c871 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00001.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00001.png new file mode 100644 index 000000000..67b6fe97a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00002.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00002.png new file mode 100644 index 000000000..3fb69ef06 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00003.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00003.png new file mode 100644 index 000000000..0715daaae Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00004.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_all_chain_whitelisted/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00000.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00000.png new file mode 100644 index 000000000..af780c871 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00001.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00001.png new file mode 100644 index 000000000..6b2e18654 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00002.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00002.png new file mode 100644 index 000000000..3fb69ef06 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00003.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00003.png new file mode 100644 index 000000000..0715daaae Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00004.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_max/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_wrong_chain/00000.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_wrong_chain/00000.png new file mode 100644 index 000000000..303a15df2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_wrong_chain/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_wrong_chain/00001.png b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_wrong_chain/00001.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_in_whitelist_wrong_chain/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_not_enabled/00000.png b/tests/ragger/snapshots/apex_p/test_eip7702_not_enabled/00000.png new file mode 100644 index 000000000..405d30280 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_not_enabled/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_not_enabled/00001.png b/tests/ragger/snapshots/apex_p/test_eip7702_not_enabled/00001.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_not_enabled/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_not_in_whitelist/00000.png b/tests/ragger/snapshots/apex_p/test_eip7702_not_in_whitelist/00000.png new file mode 100644 index 000000000..303a15df2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_not_in_whitelist/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_not_in_whitelist/00001.png b/tests/ragger/snapshots/apex_p/test_eip7702_not_in_whitelist/00001.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_not_in_whitelist/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00000.png b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00000.png new file mode 100644 index 000000000..12c7faf71 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00001.png b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00001.png new file mode 100644 index 000000000..bb452af74 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00002.png b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00002.png new file mode 100644 index 000000000..5bbee535d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00003.png b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00003.png new file mode 100644 index 000000000..0715daaae Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00004.png b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_eip7702_revocation/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_1inch/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00000.png new file mode 100644 index 000000000..5b6f38e82 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_1inch/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00001.png new file mode 100644 index 000000000..5937a52b8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_1inch/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00002.png new file mode 100644 index 000000000..4e2f8b1de Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_1inch/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00003.png new file mode 100644 index 000000000..3648fc422 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_1inch/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_1inch/00005.png b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_1inch/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_4226/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_4226/00000.png new file mode 100644 index 000000000..2e2bc89c1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_4226/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_4226/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_4226/00001.png new file mode 100644 index 000000000..695ba6a56 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_4226/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_4226/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_4226/00002.png new file mode 100644 index 000000000..3f8638dd7 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_4226/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_4226/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_4226/00003.png new file mode 100644 index 000000000..01df4a64c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_4226/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_4226/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_4226/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_4226/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_4226/00005.png b/tests/ragger/snapshots/apex_p/test_gcs_4226/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_4226/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00000.png new file mode 100644 index 000000000..d2d73a3e5 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00001.png new file mode 100644 index 000000000..684b9bdfe Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00002.png new file mode 100644 index 000000000..958156559 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00003.png new file mode 100644 index 000000000..1de5b2e14 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00004.png new file mode 100644 index 000000000..20bd00da8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00005.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00005.png new file mode 100644 index 000000000..008822104 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00006.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00006.png new file mode 100644 index 000000000..fb8bb89a6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00007.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00007.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00007.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00008.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00008.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_createProxyWithNonce/00008.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png new file mode 100644 index 000000000..a0537d8dd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png new file mode 100644 index 000000000..c0996c4db Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png new file mode 100644 index 000000000..af7e59735 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png new file mode 100644 index 000000000..4bc9ea1be Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png new file mode 100644 index 000000000..477765edf Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png new file mode 100644 index 000000000..4d595cc9e Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png new file mode 100644 index 000000000..616614973 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png new file mode 100644 index 000000000..539671d15 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00000.png new file mode 100644 index 000000000..a0537d8dd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00001.png new file mode 100644 index 000000000..c0996c4db Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00002.png new file mode 100644 index 000000000..2e0eb9025 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00003.png new file mode 100644 index 000000000..fbf0b8ade Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00004.png new file mode 100644 index 000000000..694b9a09c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00005.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00005.png new file mode 100644 index 000000000..9b75e2e31 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00006.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00006.png new file mode 100644 index 000000000..38e592542 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00007.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00007.png new file mode 100644 index 000000000..539671d15 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00007.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00008.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00008.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00008.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00009.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00009.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_changeThreshold/00009.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00000.png new file mode 100644 index 000000000..f70ea307b Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00001.png new file mode 100644 index 000000000..d7923b9b8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00002.png new file mode 100644 index 000000000..c4b8909a4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00003.png new file mode 100644 index 000000000..11d08861d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00005.png b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nested_execTransaction_send/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nft/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_nft/00000.png new file mode 100644 index 000000000..dd682cd5e Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nft/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nft/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_nft/00001.png new file mode 100644 index 000000000..2ff0bd1b6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nft/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nft/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_nft/00002.png new file mode 100644 index 000000000..e645eb7d9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nft/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nft/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_nft/00003.png new file mode 100644 index 000000000..4e910ae92 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nft/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nft/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_nft/00004.png new file mode 100644 index 000000000..a9e38da55 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nft/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nft/00005.png b/tests/ragger/snapshots/apex_p/test_gcs_nft/00005.png new file mode 100644 index 000000000..f5eadcbef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nft/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nft/00006.png b/tests/ragger/snapshots/apex_p/test_gcs_nft/00006.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nft/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_nft/00007.png b/tests/ragger/snapshots/apex_p/test_gcs_nft/00007.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_nft/00007.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_poap/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_poap/00000.png new file mode 100644 index 000000000..aa8ea3867 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_poap/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_poap/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_poap/00001.png new file mode 100644 index 000000000..fbd56f28a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_poap/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_poap/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_poap/00002.png new file mode 100644 index 000000000..7c431f288 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_poap/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_poap/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_poap/00003.png new file mode 100644 index 000000000..819bfc394 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_poap/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_poap/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_poap/00004.png new file mode 100644 index 000000000..a39d95b8c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_poap/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_poap/00005.png b/tests/ragger/snapshots/apex_p/test_gcs_poap/00005.png new file mode 100644 index 000000000..dceddffce Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_poap/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_poap/00006.png b/tests/ragger/snapshots/apex_p/test_gcs_poap/00006.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_poap/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_poap/00007.png b/tests/ragger/snapshots/apex_p/test_gcs_poap/00007.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_poap/00007.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_proxy/00000.png b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00000.png new file mode 100644 index 000000000..4ed607ff4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_proxy/00001.png b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00001.png new file mode 100644 index 000000000..15a2442b6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_proxy/00002.png b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00002.png new file mode 100644 index 000000000..69493d468 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_proxy/00003.png b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00003.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_gcs_proxy/00004.png b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_gcs_proxy/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00000.png b/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00000.png new file mode 100644 index 000000000..d8dc9f5df Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00001.png b/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00001.png new file mode 100644 index 000000000..70e22351a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00002.png b/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00002.png new file mode 100644 index 000000000..6ce358d61 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00003.png b/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_eth2_pk/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_1/00000.png b/tests/ragger/snapshots/apex_p/test_get_pk_1/00000.png new file mode 100644 index 000000000..7cdb21cc9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_1/00001.png b/tests/ragger/snapshots/apex_p/test_get_pk_1/00001.png new file mode 100644 index 000000000..19dbb5d6d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_1/00002.png b/tests/ragger/snapshots/apex_p/test_get_pk_1/00002.png new file mode 100644 index 000000000..6ce358d61 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_1/00003.png b/tests/ragger/snapshots/apex_p/test_get_pk_1/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_137/00000.png b/tests/ragger/snapshots/apex_p/test_get_pk_137/00000.png new file mode 100644 index 000000000..b9bb25589 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_137/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_137/00001.png b/tests/ragger/snapshots/apex_p/test_get_pk_137/00001.png new file mode 100644 index 000000000..19dbb5d6d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_137/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_137/00002.png b/tests/ragger/snapshots/apex_p/test_get_pk_137/00002.png new file mode 100644 index 000000000..6ce358d61 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_137/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_137/00003.png b/tests/ragger/snapshots/apex_p/test_get_pk_137/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_137/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_2/00000.png b/tests/ragger/snapshots/apex_p/test_get_pk_2/00000.png new file mode 100644 index 000000000..6fcf27bdc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_2/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_2/00001.png b/tests/ragger/snapshots/apex_p/test_get_pk_2/00001.png new file mode 100644 index 000000000..19dbb5d6d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_2/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_2/00002.png b/tests/ragger/snapshots/apex_p/test_get_pk_2/00002.png new file mode 100644 index 000000000..6ce358d61 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_2/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_2/00003.png b/tests/ragger/snapshots/apex_p/test_get_pk_2/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_2/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_5/00000.png b/tests/ragger/snapshots/apex_p/test_get_pk_5/00000.png new file mode 100644 index 000000000..c2dacd509 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_5/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_5/00001.png b/tests/ragger/snapshots/apex_p/test_get_pk_5/00001.png new file mode 100644 index 000000000..19dbb5d6d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_5/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_5/00002.png b/tests/ragger/snapshots/apex_p/test_get_pk_5/00002.png new file mode 100644 index 000000000..6ce358d61 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_5/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_5/00003.png b/tests/ragger/snapshots/apex_p/test_get_pk_5/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_5/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_None/00000.png b/tests/ragger/snapshots/apex_p/test_get_pk_None/00000.png new file mode 100644 index 000000000..7cdb21cc9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_None/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_None/00001.png b/tests/ragger/snapshots/apex_p/test_get_pk_None/00001.png new file mode 100644 index 000000000..19dbb5d6d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_None/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_None/00002.png b/tests/ragger/snapshots/apex_p/test_get_pk_None/00002.png new file mode 100644 index 000000000..6ce358d61 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_None/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_None/00003.png b/tests/ragger/snapshots/apex_p/test_get_pk_None/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_None/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00000.png b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00000.png new file mode 100644 index 000000000..7cdb21cc9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00001.png b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00001.png new file mode 100644 index 000000000..19dbb5d6d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00002.png b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00002.png new file mode 100644 index 000000000..0f7f5fe41 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00003.png b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_60/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00000.png b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00000.png new file mode 100644 index 000000000..7cdb21cc9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00001.png b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00001.png new file mode 100644 index 000000000..fbb305ff2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00002.png b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00002.png new file mode 100644 index 000000000..0f7f5fe41 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00003.png b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_get_pk_rejected_700/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00000.png new file mode 100644 index 000000000..7ca460be8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00001.png new file mode 100644 index 000000000..eaa15f222 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00002.png new file mode 100644 index 000000000..cd8e1e902 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00003.png new file mode 100644 index 000000000..9f4ad35cb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00004.png new file mode 100644 index 000000000..4e2a45a1f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00005.png new file mode 100644 index 000000000..cf109394f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00006.png new file mode 100644 index 000000000..1d65a5392 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00007.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00007.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_reject_safeTransferFrom_1/00007.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00000.png new file mode 100644 index 000000000..dcf35353b Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00001.png new file mode 100644 index 000000000..eaa15f222 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00002.png new file mode 100644 index 000000000..5dd1510d3 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00003.png new file mode 100644 index 000000000..fb51a452a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00004.png new file mode 100644 index 000000000..d159e3edb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_1/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00000.png new file mode 100644 index 000000000..066466c7e Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00001.png new file mode 100644 index 000000000..0972c9d5f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00002.png new file mode 100644 index 000000000..f625502a8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00003.png new file mode 100644 index 000000000..d1c0829d6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00004.png new file mode 100644 index 000000000..fe3ed8b51 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_137/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00000.png new file mode 100644 index 000000000..540119395 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00001.png new file mode 100644 index 000000000..0972c9d5f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00002.png new file mode 100644 index 000000000..d93330343 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00003.png new file mode 100644 index 000000000..fb51a452a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00004.png new file mode 100644 index 000000000..8c9c5c4d9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeBatchTransferFrom_5/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00000.png new file mode 100644 index 000000000..7ca460be8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00001.png new file mode 100644 index 000000000..eaa15f222 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00002.png new file mode 100644 index 000000000..cd8e1e902 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00003.png new file mode 100644 index 000000000..9f4ad35cb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00004.png new file mode 100644 index 000000000..4e2a45a1f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_1/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00000.png new file mode 100644 index 000000000..7153cd794 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00001.png new file mode 100644 index 000000000..0972c9d5f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00002.png new file mode 100644 index 000000000..892833ef5 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00003.png new file mode 100644 index 000000000..fa6bfed08 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00004.png new file mode 100644 index 000000000..2b24a8515 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_137/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00000.png new file mode 100644 index 000000000..cc88af184 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00001.png new file mode 100644 index 000000000..0972c9d5f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00002.png new file mode 100644 index 000000000..98d132a44 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00003.png new file mode 100644 index 000000000..f6673a28a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00004.png new file mode 100644 index 000000000..7c5a5cd80 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_safeTransferFrom_5/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00000.png new file mode 100644 index 000000000..a541de186 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00001.png new file mode 100644 index 000000000..9b15e5619 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00002.png new file mode 100644 index 000000000..ff1afd650 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00003.png new file mode 100644 index 000000000..74261aff0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00000.png new file mode 100644 index 000000000..dd345bcb9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00001.png new file mode 100644 index 000000000..5eb5afa51 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00002.png new file mode 100644 index 000000000..2a3f3a155 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00003.png new file mode 100644 index 000000000..e57ef07ea Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_137/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00000.png new file mode 100644 index 000000000..5dda0fd5c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00001.png new file mode 100644 index 000000000..5eb5afa51 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00002.png new file mode 100644 index 000000000..61ddeff24 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00003.png new file mode 100644 index 000000000..9480228bd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc1155_setApprovalForAll_5/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00000.png new file mode 100644 index 000000000..a541de186 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00001.png new file mode 100644 index 000000000..79e5fc272 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00002.png new file mode 100644 index 000000000..9ba4a7282 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00003.png new file mode 100644 index 000000000..74261aff0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00000.png new file mode 100644 index 000000000..8e0ee5099 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00001.png new file mode 100644 index 000000000..ad52aac05 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00002.png new file mode 100644 index 000000000..daa0b0c38 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00003.png new file mode 100644 index 000000000..d1c0829d6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00004.png new file mode 100644 index 000000000..1f3ea4086 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_137/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00000.png new file mode 100644 index 000000000..5018e865c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00001.png new file mode 100644 index 000000000..b56acdfa3 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00002.png new file mode 100644 index 000000000..bab7fccb0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00003.png new file mode 100644 index 000000000..fb51a452a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00004.png new file mode 100644 index 000000000..28c995a9c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_approve_5/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00000.png new file mode 100644 index 000000000..b30012a59 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00001.png new file mode 100644 index 000000000..30323cdd6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00002.png new file mode 100644 index 000000000..9ba4a7282 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00003.png new file mode 100644 index 000000000..591770564 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00004.png new file mode 100644 index 000000000..cf109394f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00005.png new file mode 100644 index 000000000..1d65a5392 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_reject_safeTransferFrom_1/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00000.png new file mode 100644 index 000000000..b30012a59 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00001.png new file mode 100644 index 000000000..30323cdd6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00002.png new file mode 100644 index 000000000..9ba4a7282 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00003.png new file mode 100644 index 000000000..591770564 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00000.png new file mode 100644 index 000000000..7153cd794 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00001.png new file mode 100644 index 000000000..4679e56d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00002.png new file mode 100644 index 000000000..daa0b0c38 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00003.png new file mode 100644 index 000000000..d1c0829d6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00004.png new file mode 100644 index 000000000..2b24a8515 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_137/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00000.png new file mode 100644 index 000000000..cc88af184 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00001.png new file mode 100644 index 000000000..f823484c4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00002.png new file mode 100644 index 000000000..bab7fccb0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00003.png new file mode 100644 index 000000000..fb51a452a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00004.png new file mode 100644 index 000000000..7c5a5cd80 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_safeTransferFrom_5/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00000.png new file mode 100644 index 000000000..a541de186 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00001.png new file mode 100644 index 000000000..f21029329 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00002.png new file mode 100644 index 000000000..8b39b9ac7 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00003.png new file mode 100644 index 000000000..74261aff0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00000.png new file mode 100644 index 000000000..dd345bcb9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00001.png new file mode 100644 index 000000000..00d4fb73d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00002.png new file mode 100644 index 000000000..5d5b8f0b1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00003.png new file mode 100644 index 000000000..e57ef07ea Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_137/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00000.png new file mode 100644 index 000000000..5dda0fd5c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00001.png new file mode 100644 index 000000000..a7a61636a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00002.png new file mode 100644 index 000000000..d6e5378af Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00003.png new file mode 100644 index 000000000..9480228bd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_setApprovalForAll_5/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00000.png new file mode 100644 index 000000000..b30012a59 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00001.png new file mode 100644 index 000000000..30323cdd6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00002.png new file mode 100644 index 000000000..9ba4a7282 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00003.png new file mode 100644 index 000000000..591770564 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00000.png new file mode 100644 index 000000000..7153cd794 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00001.png new file mode 100644 index 000000000..4679e56d0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00002.png new file mode 100644 index 000000000..daa0b0c38 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00003.png new file mode 100644 index 000000000..d1c0829d6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00004.png new file mode 100644 index 000000000..2b24a8515 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_137/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00000.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00000.png new file mode 100644 index 000000000..cc88af184 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00001.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00001.png new file mode 100644 index 000000000..f823484c4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00002.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00002.png new file mode 100644 index 000000000..bab7fccb0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00003.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00003.png new file mode 100644 index 000000000..fb51a452a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00004.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00004.png new file mode 100644 index 000000000..7c5a5cd80 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00005.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00005.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00006.png b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_nft_erc721_transferFrom_5/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00000.png b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00000.png new file mode 100644 index 000000000..427cb17cc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00001.png b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00001.png new file mode 100644 index 000000000..164e2284b Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00002.png b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00002.png new file mode 100644 index 000000000..020290e3c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00003.png b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00004.png b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_metamask/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00000.png b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00000.png new file mode 100644 index 000000000..427cb17cc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00001.png b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00001.png new file mode 100644 index 000000000..d4cbce0ea Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00002.png b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00002.png new file mode 100644 index 000000000..020290e3c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00003.png b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00004.png b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_non_ascii/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00000.png b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00000.png new file mode 100644 index 000000000..427cb17cc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00001.png b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00001.png new file mode 100644 index 000000000..7166e0e80 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00002.png b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00002.png new file mode 100644 index 000000000..020290e3c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00003.png b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00004.png b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_opensea/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00000.png b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00000.png new file mode 100644 index 000000000..427cb17cc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00001.png b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00001.png new file mode 100644 index 000000000..fbb2b2998 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00002.png b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00002.png new file mode 100644 index 000000000..020290e3c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00003.png b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00003.png new file mode 100644 index 000000000..419b6166c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00004.png b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00004.png new file mode 100644 index 000000000..f411cb48d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00005.png b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_personal_sign_reject/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_safe_descriptor/00000.png b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00000.png new file mode 100644 index 000000000..147c55bd9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_safe_descriptor/00001.png b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00001.png new file mode 100644 index 000000000..56fea6a5d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_safe_descriptor/00002.png b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00002.png new file mode 100644 index 000000000..57a8bf1ca Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_safe_descriptor/00003.png b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00003.png new file mode 100644 index 000000000..396042c86 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_safe_descriptor/00004.png b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_safe_descriptor/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00000.png b/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00001.png b/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00002.png b/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00002.png new file mode 100644 index 000000000..28630f782 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00003.png b/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00003.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/blind_sign/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/debug_token/00000.png b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/debug_token/00001.png b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/debug_token/00002.png b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00002.png new file mode 100644 index 000000000..d6afd0094 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/debug_token/00003.png b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00003.png new file mode 100644 index 000000000..093ef0ac1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/debug_token/00004.png b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00004.png new file mode 100644 index 000000000..4ad9f7787 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/debug_token/00005.png b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/debug_token/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00000.png b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00001.png b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00002.png b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00002.png new file mode 100644 index 000000000..d6afd0094 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00003.png b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00003.png new file mode 100644 index 000000000..2a47e9906 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00004.png b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/eip712_token/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/hash/00000.png b/tests/ragger/snapshots/apex_p/test_settings/hash/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/hash/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/hash/00001.png b/tests/ragger/snapshots/apex_p/test_settings/hash/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/hash/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/hash/00002.png b/tests/ragger/snapshots/apex_p/test_settings/hash/00002.png new file mode 100644 index 000000000..d6afd0094 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/hash/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/hash/00003.png b/tests/ragger/snapshots/apex_p/test_settings/hash/00003.png new file mode 100644 index 000000000..093ef0ac1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/hash/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/hash/00004.png b/tests/ragger/snapshots/apex_p/test_settings/hash/00004.png new file mode 100644 index 000000000..bf28052af Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/hash/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/hash/00005.png b/tests/ragger/snapshots/apex_p/test_settings/hash/00005.png new file mode 100644 index 000000000..cfcf56d94 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/hash/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/hash/00006.png b/tests/ragger/snapshots/apex_p/test_settings/hash/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/hash/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple1/00000.png b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple1/00001.png b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple1/00002.png b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00002.png new file mode 100644 index 000000000..28630f782 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple1/00003.png b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00003.png new file mode 100644 index 000000000..d6afd0094 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple1/00004.png b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00004.png new file mode 100644 index 000000000..093ef0ac1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple1/00005.png b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00005.png new file mode 100644 index 000000000..4ad9f7787 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple1/00006.png b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple1/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple2/00000.png b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple2/00001.png b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple2/00002.png b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00002.png new file mode 100644 index 000000000..28630f782 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple2/00003.png b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00003.png new file mode 100644 index 000000000..d6afd0094 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple2/00004.png b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00004.png new file mode 100644 index 000000000..2a47e9906 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple2/00005.png b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple2/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple3/00000.png b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple3/00001.png b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple3/00002.png b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00002.png new file mode 100644 index 000000000..00453d13c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple3/00003.png b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00003.png new file mode 100644 index 000000000..d056f2572 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple3/00004.png b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00004.png new file mode 100644 index 000000000..7175b920d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple3/00005.png b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00005.png new file mode 100644 index 000000000..917a95f57 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/multiple3/00006.png b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/multiple3/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/nonce/00000.png b/tests/ragger/snapshots/apex_p/test_settings/nonce/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/nonce/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/nonce/00001.png b/tests/ragger/snapshots/apex_p/test_settings/nonce/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/nonce/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/nonce/00002.png b/tests/ragger/snapshots/apex_p/test_settings/nonce/00002.png new file mode 100644 index 000000000..d6afd0094 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/nonce/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/nonce/00003.png b/tests/ragger/snapshots/apex_p/test_settings/nonce/00003.png new file mode 100644 index 000000000..4c9588893 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/nonce/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/nonce/00004.png b/tests/ragger/snapshots/apex_p/test_settings/nonce/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/nonce/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00000.png b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00000.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00001.png b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00001.png new file mode 100644 index 000000000..e24eb55eb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00002.png b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00002.png new file mode 100644 index 000000000..00453d13c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00003.png b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00003.png new file mode 100644 index 000000000..d056f2572 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00004.png b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00004.png new file mode 100644 index 000000000..7175b920d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00005.png b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_settings/tx_checks/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00000.png b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00000.png new file mode 100644 index 000000000..3e1a42ea8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00001.png b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00001.png new file mode 100644 index 000000000..7a2bd22b6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00002.png b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00002.png new file mode 100644 index 000000000..7ffa0b5b1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00003.png b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00003.png new file mode 100644 index 000000000..a7e47de5e Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00004.png b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00005.png b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_2930/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00000.png b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00001.png b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00001.png new file mode 100644 index 000000000..13da58fe7 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00002.png b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00002.png new file mode 100644 index 000000000..3d2a02642 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00003.png b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00004.png b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00005.png b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_eip_7702/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00000.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00000.png new file mode 100644 index 000000000..f8a4ec8e1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00001.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00001.png new file mode 100644 index 000000000..4f29f628f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00002.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00002.png new file mode 100644 index 000000000..076f97045 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00003.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00003.png new file mode 100644 index 000000000..6d2cec6f2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00004.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00005.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_chainid/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00000.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00000.png new file mode 100644 index 000000000..993976d21 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00001.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00001.png new file mode 100644 index 000000000..50291077d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00002.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00002.png new file mode 100644 index 000000000..95fb8675b Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00003.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00003.png new file mode 100644 index 000000000..1b0adb2a0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00004.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00005.png b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_legacy_send_bsc/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00000.png b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00001.png b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00001.png new file mode 100644 index 000000000..215a98008 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00002.png b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00002.png new file mode 100644 index 000000000..ee75eaa60 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00003.png b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00004.png b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00005.png b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_limit_nonce/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00000.png b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00001.png b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00001.png new file mode 100644 index 000000000..e32140857 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00002.png b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00002.png new file mode 100644 index 000000000..3d4a3c08c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00003.png b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00004.png b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00005.png b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_nonce_display/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00000.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00000.png new file mode 100644 index 000000000..1bb01a02c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00001.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00001.png new file mode 100644 index 000000000..0ea6b93a7 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00002.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00002.png new file mode 100644 index 000000000..6072a4e5a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00003.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00003.png new file mode 100644 index 000000000..d58328df2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00004.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00004.png new file mode 100644 index 000000000..6f1308aaa Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00005.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00005.png new file mode 100644 index 000000000..02639fdd2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00006.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00006.png new file mode 100644 index 000000000..eb1e09fcd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00007.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00007.png new file mode 100644 index 000000000..0418b7642 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00007.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00008.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00008.png new file mode 100644 index 000000000..68627c2ef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00008.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00009.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00009.png new file mode 100644 index 000000000..315705fde Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00009.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00010.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00010.png new file mode 100644 index 000000000..148e6b5a1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00010.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00011.png b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00011.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_parameter_selector/00011.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_reject/00000.png b/tests/ragger/snapshots/apex_p/test_sign_reject/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_reject/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_reject/00001.png b/tests/ragger/snapshots/apex_p/test_sign_reject/00001.png new file mode 100644 index 000000000..e32140857 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_reject/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_reject/00002.png b/tests/ragger/snapshots/apex_p/test_sign_reject/00002.png new file mode 100644 index 000000000..23f1c58f8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_reject/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_reject/00003.png b/tests/ragger/snapshots/apex_p/test_sign_reject/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_reject/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_reject/00004.png b/tests/ragger/snapshots/apex_p/test_sign_reject/00004.png new file mode 100644 index 000000000..cf109394f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_reject/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_reject/00005.png b/tests/ragger/snapshots/apex_p/test_sign_reject/00005.png new file mode 100644 index 000000000..1d65a5392 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_reject/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_reject/00006.png b/tests/ragger/snapshots/apex_p/test_sign_reject/00006.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_reject/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple/00000.png b/tests/ragger/snapshots/apex_p/test_sign_simple/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple/00001.png b/tests/ragger/snapshots/apex_p/test_sign_simple/00001.png new file mode 100644 index 000000000..e32140857 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple/00002.png b/tests/ragger/snapshots/apex_p/test_sign_simple/00002.png new file mode 100644 index 000000000..23f1c58f8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple/00003.png b/tests/ragger/snapshots/apex_p/test_sign_simple/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple/00004.png b/tests/ragger/snapshots/apex_p/test_sign_simple/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple/00005.png b/tests/ragger/snapshots/apex_p/test_sign_simple/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00000.png b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00001.png b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00001.png new file mode 100644 index 000000000..e32140857 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00002.png b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00002.png new file mode 100644 index 000000000..f465850a0 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00003.png b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00004.png b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00005.png b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_sign_simple_display_hash/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00000.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00001.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00001.png new file mode 100644 index 000000000..6e6806442 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00002.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00002.png new file mode 100644 index 000000000..23f1c58f8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00003.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00004.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00005.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00000.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00000.png new file mode 100644 index 000000000..521a7e781 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00001.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00001.png new file mode 100644 index 000000000..6e6806442 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00002.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00002.png new file mode 100644 index 000000000..8acf1a6f4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00003.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00003.png new file mode 100644 index 000000000..cc1536e0f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00004.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00005.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_non_mainnet/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00000.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00000.png new file mode 100644 index 000000000..f8a4ec8e1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00001.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00001.png new file mode 100644 index 000000000..c30236dbd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00002.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00002.png new file mode 100644 index 000000000..c8a9fd781 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00003.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00003.png new file mode 100644 index 000000000..6d2cec6f2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00004.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00005.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_unknown_chain/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00000.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00001.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00001.png new file mode 100644 index 000000000..6e6806442 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00002.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00002.png new file mode 100644 index 000000000..4e9e27914 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00000.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00000.png new file mode 100644 index 000000000..6e6806442 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00001.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00001.png new file mode 100644 index 000000000..23f1c58f8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00002.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00002.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00003.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00003.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00004.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_verbose/part2/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00000.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00001.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00001.png new file mode 100644 index 000000000..4020017ef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00002.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00002.png new file mode 100644 index 000000000..23f1c58f8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00003.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00004.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00005.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v1_wrong_addr/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00000.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00000.png new file mode 100644 index 000000000..0ba97c79d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00001.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00001.png new file mode 100644 index 000000000..6e6806442 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00002.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00002.png new file mode 100644 index 000000000..23f1c58f8 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00003.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00003.png new file mode 100644 index 000000000..3e448e779 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00004.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00005.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00000.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00000.png new file mode 100644 index 000000000..f8a4ec8e1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00001.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00001.png new file mode 100644 index 000000000..c30236dbd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00002.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00002.png new file mode 100644 index 000000000..a22db1cbd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00003.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00003.png new file mode 100644 index 000000000..6d2cec6f2 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00004.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00005.png b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_trusted_name_v2_wrong_chainid/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00000.png new file mode 100644 index 000000000..cba40cb0a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00001.png new file mode 100644 index 000000000..68627c2ef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00002.png new file mode 100644 index 000000000..315705fde Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00003.png new file mode 100644 index 000000000..148e6b5a1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/warning/00000.png new file mode 100644 index 000000000..eb1e09fcd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_benign/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00000.png new file mode 100644 index 000000000..33508763c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00001.png new file mode 100644 index 000000000..68627c2ef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00002.png new file mode 100644 index 000000000..315705fde Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00003.png new file mode 100644 index 000000000..148e6b5a1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/warning/00000.png new file mode 100644 index 000000000..eb1e09fcd Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_issue/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00000.png new file mode 100644 index 000000000..ff765fb1b Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00001.png new file mode 100644 index 000000000..68627c2ef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00002.png new file mode 100644 index 000000000..315705fde Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00003.png new file mode 100644 index 000000000..f0a86ca19 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/warning/00000.png new file mode 100644 index 000000000..2fc331c18 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_threat/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00000.png new file mode 100644 index 000000000..aeab83f3c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00001.png new file mode 100644 index 000000000..68627c2ef Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00002.png new file mode 100644 index 000000000..315705fde Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00003.png new file mode 100644 index 000000000..148e6b5a1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/warning/00000.png new file mode 100644 index 000000000..7da9b1757 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_blind_sign_warning/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00000.png new file mode 100644 index 000000000..dba2e93b1 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00001.png new file mode 100644 index 000000000..2fd3dc0da Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00002.png new file mode 100644 index 000000000..cd24cc851 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00003.png new file mode 100644 index 000000000..d0ceff0a9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00004.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/warning/00000.png new file mode 100644 index 000000000..2fc331c18 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_eip712/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00000.png new file mode 100644 index 000000000..8a6c1b2cb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00001.png new file mode 100644 index 000000000..fbd56f28a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00002.png new file mode 100644 index 000000000..7c431f288 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00003.png new file mode 100644 index 000000000..819bfc394 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00004.png new file mode 100644 index 000000000..a39d95b8c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00005.png new file mode 100644 index 000000000..98b142fbb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00006.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00006.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00006.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00007.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00007.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/00007.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/warning/00000.png new file mode 100644 index 000000000..7da9b1757 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_gcs/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00000.png new file mode 100644 index 000000000..dadf85ba9 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00001.png new file mode 100644 index 000000000..30323cdd6 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00002.png new file mode 100644 index 000000000..9ba4a7282 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00003.png new file mode 100644 index 000000000..5300d928a Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png new file mode 100644 index 000000000..7da9b1757 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_nft_safeTransferFrom_1/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00000.png new file mode 100644 index 000000000..052bec6dc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00001.png new file mode 100644 index 000000000..8fa38155d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00002.png new file mode 100644 index 000000000..8acf1a6f4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00003.png new file mode 100644 index 000000000..d4d9bc2d5 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_no_simu/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_opt_in/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_opt_in/00000.png new file mode 100644 index 000000000..00453d13c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_opt_in/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_opt_in/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_opt_in/00001.png new file mode 100644 index 000000000..d056f2572 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_opt_in/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00000.png new file mode 100644 index 000000000..536434e3f Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00001.png new file mode 100644 index 000000000..8fa38155d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00002.png new file mode 100644 index 000000000..8acf1a6f4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00003.png new file mode 100644 index 000000000..267ef791d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_benign/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00000.png new file mode 100644 index 000000000..052bec6dc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00001.png new file mode 100644 index 000000000..8fa38155d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00002.png new file mode 100644 index 000000000..8acf1a6f4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00003.png new file mode 100644 index 000000000..d4d9bc2d5 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_issue/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00000.png new file mode 100644 index 000000000..ac003e1d4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00001.png new file mode 100644 index 000000000..8fa38155d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00002.png new file mode 100644 index 000000000..8acf1a6f4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00003.png new file mode 100644 index 000000000..c6e6cfcbc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/warning/00000.png new file mode 100644 index 000000000..2fc331c18 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_threat/warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00000.png new file mode 100644 index 000000000..c6f4cd3cb Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00000.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00001.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00001.png new file mode 100644 index 000000000..8fa38155d Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00001.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00002.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00002.png new file mode 100644 index 000000000..8acf1a6f4 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00002.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00003.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00003.png new file mode 100644 index 000000000..d4fdedc07 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00003.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00004.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00004.png new file mode 100644 index 000000000..4aba0a2bc Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00004.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00005.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00005.png new file mode 100644 index 000000000..0a471a44c Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/00005.png differ diff --git a/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/warning/00000.png b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/warning/00000.png new file mode 100644 index 000000000..7da9b1757 Binary files /dev/null and b/tests/ragger/snapshots/apex_p/test_tx_simulation_sign_warning/warning/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00000.png index 14713d83b..69165fc87 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00001.png index 074830272..dd3329d2f 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00002.png index 683ec23b7..6c20a2d98 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00003.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00003.png index 8232708bf..d47da0b3d 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00003.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00004.png index cbaa88901..00e23ff03 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00004.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_blind_sign_nonce_nonzero/00006.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00006.png similarity index 100% rename from tests/ragger/snapshots/flex/test_blind_sign_nonce_nonzero/00006.png rename to tests/ragger/snapshots/flex/test_eip712_advanced_filtering-verbose/00006.png diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00000.png index 14713d83b..9e981a99f 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00001.png index 074830272..43a1c0e69 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00002.png index 683ec23b7..450785ec2 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00003.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00003.png index cbaa88901..9fc042f7b 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00003.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/eip712_token/00005.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00005.png similarity index 100% rename from tests/ragger/snapshots/flex/test_settings/eip712_token/00005.png rename to tests/ragger/snapshots/flex/test_eip712_advanced_filtering/00005.png diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00001.png index 36ee846ff..b6fd2817c 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_settings/multiple2/00006.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00004.png similarity index 100% rename from tests/ragger/snapshots/flex/test_settings/multiple2/00006.png rename to tests/ragger/snapshots/flex/test_eip712_advanced_filtering_permit/00004.png diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00001.png index 62be9a33a..a1ded918f 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_filtering_unlimited/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00001.png index ca4567bf7..1beedba68 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-False-True/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00001.png index d2b6f4138..cc8f0d04e 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_missing_token-True-False/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00001.png index 897ec3706..332771e6c 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png index 897ec3706..332771e6c 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00001.png index 015f0dfdf..3c7d63cc8 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png index 897ec3706..332771e6c 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00001.png index 015f0dfdf..3c7d63cc8 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png index 00fcc93ac..f569ac8f0 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00001.png index 00fcc93ac..f569ac8f0 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png index 00fcc93ac..f569ac8f0 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata/00000.png b/tests/ragger/snapshots/flex/test_eip712_calldata/00000.png new file mode 100644 index 000000000..16e934fb9 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata/00001.png b/tests/ragger/snapshots/flex/test_eip712_calldata/00001.png new file mode 100644 index 000000000..3af355e6c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata/00002.png b/tests/ragger/snapshots/flex/test_eip712_calldata/00002.png new file mode 100644 index 000000000..b50d1e230 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata/00003.png b/tests/ragger/snapshots/flex/test_eip712_calldata/00003.png new file mode 100644 index 000000000..8b981d44c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata/00004.png b/tests/ragger/snapshots/flex/test_eip712_calldata/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00000.png b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00000.png new file mode 100644 index 000000000..9e981a99f Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00001.png b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00001.png new file mode 100644 index 000000000..fcd07cbde Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00002.png b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00002.png new file mode 100644 index 000000000..1bb1467c0 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00003.png b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00003.png new file mode 100644 index 000000000..9fc042f7b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00004.png b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00004.png new file mode 100644 index 000000000..8b981d44c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00005.png b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00005.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_calldata_empty_send/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00000.png b/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00000.png index 14713d83b..16e934fb9 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00000.png and b/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00001.png b/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00001.png index 7d202e913..072c04ace 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00001.png and b/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00002.png b/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00002.png index cbaa88901..b50d1e230 100644 Binary files a/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00002.png and b/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00004.png b/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_eip712_filtering_empty_array/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00000.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00000.png new file mode 100644 index 000000000..1c5442eb3 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00001.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00001.png new file mode 100644 index 000000000..7a8de5c72 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00002.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00002.png new file mode 100644 index 000000000..185e53b5c Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00003.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00003.png new file mode 100644 index 000000000..80edf1b89 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00004.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00004.png new file mode 100644 index 000000000..9655d3d88 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00005.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00005.png new file mode 100644 index 000000000..49680ee9a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00006.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00006.png new file mode 100644 index 000000000..c2b88cdbf Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00007.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00007.png new file mode 100644 index 000000000..be51a9d55 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00007.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00008.png b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00008.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_createProxyWithNonce/00008.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png new file mode 100644 index 000000000..dcbef7203 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png new file mode 100644 index 000000000..7a87475c1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png new file mode 100644 index 000000000..275f2f6cc Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png new file mode 100644 index 000000000..146b276f7 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png new file mode 100644 index 000000000..3cb4d1478 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png new file mode 100644 index 000000000..42cc1fab1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png new file mode 100644 index 000000000..b2e47a4af Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png new file mode 100644 index 000000000..f90561e4b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png new file mode 100644 index 000000000..be51a9d55 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00000.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00000.png new file mode 100644 index 000000000..dcbef7203 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00001.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00001.png new file mode 100644 index 000000000..7a87475c1 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00002.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00002.png new file mode 100644 index 000000000..fa5ad9bce Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00003.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00003.png new file mode 100644 index 000000000..a0b198c53 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00004.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00004.png new file mode 100644 index 000000000..b2781845b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00005.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00005.png new file mode 100644 index 000000000..0465af9bd Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00006.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00006.png new file mode 100644 index 000000000..631285fbb Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00006.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00007.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00007.png new file mode 100644 index 000000000..f90561e4b Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00007.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00008.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00008.png new file mode 100644 index 000000000..be51a9d55 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00008.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00009.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00009.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_changeThreshold/00009.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00000.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00000.png new file mode 100644 index 000000000..a7dbb3e2f Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00001.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00001.png new file mode 100644 index 000000000..59c8c2d0e Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00002.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00002.png new file mode 100644 index 000000000..ba2f5ef51 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00003.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00003.png new file mode 100644 index 000000000..466c58bf0 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00004.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00004.png new file mode 100644 index 000000000..be51a9d55 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00005.png b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00005.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_gcs_nested_execTransaction_send/00005.png differ diff --git a/tests/ragger/snapshots/flex/test_safe_descriptor/00000.png b/tests/ragger/snapshots/flex/test_safe_descriptor/00000.png new file mode 100644 index 000000000..2704a1008 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_safe_descriptor/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_safe_descriptor/00001.png b/tests/ragger/snapshots/flex/test_safe_descriptor/00001.png new file mode 100644 index 000000000..c78e05667 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_safe_descriptor/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_safe_descriptor/00002.png b/tests/ragger/snapshots/flex/test_safe_descriptor/00002.png new file mode 100644 index 000000000..838a1d5e6 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_safe_descriptor/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_safe_descriptor/00003.png b/tests/ragger/snapshots/flex/test_safe_descriptor/00003.png new file mode 100644 index 000000000..5ff6da77a Binary files /dev/null and b/tests/ragger/snapshots/flex/test_safe_descriptor/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_safe_descriptor/00004.png b/tests/ragger/snapshots/flex/test_safe_descriptor/00004.png new file mode 100644 index 000000000..dabe7afea Binary files /dev/null and b/tests/ragger/snapshots/flex/test_safe_descriptor/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00000.png index 8ca847f41..35b605584 100644 Binary files a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00000.png and b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00000.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00001.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00001.png index c390d045a..072c04ace 100644 Binary files a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00001.png and b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00001.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00002.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00002.png index 7d202e913..8991a1999 100644 Binary files a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00002.png and b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00002.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00003.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00003.png index b1c47066a..8b981d44c 100644 Binary files a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00003.png and b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00003.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00004.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00004.png index 8b981d44c..dabe7afea 100644 Binary files a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00004.png and b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/00004.png differ diff --git a/tests/ragger/snapshots/flex/test_tx_simulation_eip712/warning/00000.png b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/warning/00000.png new file mode 100644 index 000000000..8ca847f41 Binary files /dev/null and b/tests/ragger/snapshots/flex/test_tx_simulation_eip712/warning/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00001.png index bd2d7cd4a..f8bcb28e7 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00002.png index 51d3a4333..51dd34355 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00003.png index 8d43105a0..88adf2301 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00004.png index 9a742dcd4..029666eb5 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00005.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00005.png index e91ac495d..d099b3971 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00005.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00006.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00006.png index 6af743494..151567457 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00006.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00010.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00010.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00010.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering-verbose/00010.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00001.png index bd2d7cd4a..f8bcb28e7 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00002.png index 51d3a4333..51dd34355 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00003.png index 8d43105a0..88adf2301 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00004.png index 9a742dcd4..029666eb5 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00005.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00005.png index e91ac495d..d099b3971 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00005.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00006.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00006.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00006.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00001.png index a81dcf9df..8f3d6fa22 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00002.png index 5dafa039d..fef4ad5c5 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00003.png index 6f1a4c9dc..8a51a7d94 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_permit/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00001.png index 80dc3d3f8..6ccc0b593 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00002.png index 35b028313..f17e55f80 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00003.png index 8ab66ec55..688d18df1 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_filtering_unlimited/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00001.png index 8e09324b4..0fa4f627d 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00002.png index fc037fb8c..1beb09d7e 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00003.png index 9585bfa84..b96ff34f0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-False-True/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00001.png index 8e09324b4..0fa4f627d 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00002.png index 38877a18b..d834673e2 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00003.png index 5cf1a1685..970d3f2d2 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_missing_token-True-False/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00002.png index 9b6572c39..780bd0e0e 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png index 9b6572c39..780bd0e0e 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00002.png index 6c0876a4a..38a6be5cb 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png index 9b6572c39..780bd0e0e 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00002.png index 6c0876a4a..38a6be5cb 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png index 51ec19b7f..f6da292ec 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00002.png index 51ec19b7f..f6da292ec 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png index 51ec19b7f..f6da292ec 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png and b/tests/ragger/snapshots/nanosp/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata/00000.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00000.png new file mode 100644 index 000000000..53f11c4a5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00001.png new file mode 100644 index 000000000..99c1b1fff Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00002.png new file mode 100644 index 000000000..2c053aacc Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00003.png new file mode 100644 index 000000000..33d1209ad Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00004.png new file mode 100644 index 000000000..55bb5c874 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata/00005.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00005.png new file mode 100644 index 000000000..ab20baec2 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00000.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00000.png new file mode 100644 index 000000000..53f11c4a5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00001.png new file mode 100644 index 000000000..99c1b1fff Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00002.png new file mode 100644 index 000000000..a67fa2cf4 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00003.png new file mode 100644 index 000000000..a41088be5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00004.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00004.png new file mode 100644 index 000000000..84a03b31c Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00005.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00005.png new file mode 100644 index 000000000..55bb5c874 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00006.png b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00006.png new file mode 100644 index 000000000..ab20baec2 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_eip712_calldata_empty_send/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00001.png b/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00001.png index 7da2e2bc7..4df874c29 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00001.png and b/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00002.png b/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00002.png index a785d5e60..eea95ad22 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00002.png and b/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00003.png b/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00003.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00003.png and b/tests/ragger/snapshots/nanosp/test_eip712_filtering_empty_array/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00000.png new file mode 100644 index 000000000..bbbe24644 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00001.png new file mode 100644 index 000000000..84fdc3028 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00002.png new file mode 100644 index 000000000..ee2d2f4f8 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00003.png new file mode 100644 index 000000000..c28978ef9 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00004.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00004.png new file mode 100644 index 000000000..4270f4121 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00005.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00005.png new file mode 100644 index 000000000..e81be2796 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00006.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00006.png new file mode 100644 index 000000000..f4c030b64 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00007.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00007.png new file mode 100644 index 000000000..9b0acaf72 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00007.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00008.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00008.png new file mode 100644 index 000000000..5ed42309b Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00008.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00009.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00009.png new file mode 100644 index 000000000..23ec6c2e0 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00009.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00010.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00010.png new file mode 100644 index 000000000..d3382db05 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00010.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00011.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00011.png new file mode 100644 index 000000000..e076302d8 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00011.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00012.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00012.png new file mode 100644 index 000000000..d4a0e7118 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00012.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00013.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00013.png new file mode 100644 index 000000000..103f494a7 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00013.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00014.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00014.png new file mode 100644 index 000000000..96900c61e Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00014.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00015.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00015.png new file mode 100644 index 000000000..055fd25c6 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00015.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00016.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00016.png new file mode 100644 index 000000000..c1d53a3b0 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00016.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00017.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00017.png new file mode 100644 index 000000000..3a161194e Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_createProxyWithNonce/00017.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png new file mode 100644 index 000000000..d4a6a1beb Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png new file mode 100644 index 000000000..84fdc3028 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png new file mode 100644 index 000000000..5da961930 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png new file mode 100644 index 000000000..bb5c900b8 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png new file mode 100644 index 000000000..37002344e Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png new file mode 100644 index 000000000..9e163788f Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png new file mode 100644 index 000000000..f4c030b64 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png new file mode 100644 index 000000000..ce9f0b665 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png new file mode 100644 index 000000000..f29f9bb4d Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png new file mode 100644 index 000000000..a3246e6a5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00010.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00010.png new file mode 100644 index 000000000..de922bf7c Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00010.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00011.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00011.png new file mode 100644 index 000000000..e57699cb6 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00011.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00012.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00012.png new file mode 100644 index 000000000..ec5d9aa51 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00012.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00013.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00013.png new file mode 100644 index 000000000..74048f7e0 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00013.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00014.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00014.png new file mode 100644 index 000000000..8fb196ef4 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00014.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00015.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00015.png new file mode 100644 index 000000000..00bff5704 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00015.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00016.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00016.png new file mode 100644 index 000000000..be0cc92fc Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00016.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00017.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00017.png new file mode 100644 index 000000000..832f12e0e Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00017.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00018.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00018.png new file mode 100644 index 000000000..9abde7556 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00018.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00019.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00019.png new file mode 100644 index 000000000..c1d53a3b0 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00019.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00020.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00020.png new file mode 100644 index 000000000..3a161194e Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_addOwnerWithThreshold/00020.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00000.png new file mode 100644 index 000000000..d4a6a1beb Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00001.png new file mode 100644 index 000000000..84fdc3028 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00002.png new file mode 100644 index 000000000..5da961930 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00003.png new file mode 100644 index 000000000..bb5c900b8 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00004.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00004.png new file mode 100644 index 000000000..903f828d7 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00005.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00005.png new file mode 100644 index 000000000..c2b42b346 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00006.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00006.png new file mode 100644 index 000000000..ce9f0b665 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00007.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00007.png new file mode 100644 index 000000000..f29f9bb4d Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00007.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00008.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00008.png new file mode 100644 index 000000000..a3246e6a5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00008.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00009.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00009.png new file mode 100644 index 000000000..de922bf7c Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00009.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00010.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00010.png new file mode 100644 index 000000000..e57699cb6 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00010.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00011.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00011.png new file mode 100644 index 000000000..ec5d9aa51 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00011.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00012.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00012.png new file mode 100644 index 000000000..38954e410 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00012.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00013.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00013.png new file mode 100644 index 000000000..2dc3e5c04 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00013.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00014.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00014.png new file mode 100644 index 000000000..887efbf97 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00014.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00015.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00015.png new file mode 100644 index 000000000..54eed8c27 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00015.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00016.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00016.png new file mode 100644 index 000000000..dbf850787 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00016.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00017.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00017.png new file mode 100644 index 000000000..27be46c04 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00017.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00018.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00018.png new file mode 100644 index 000000000..c1d53a3b0 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00018.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00019.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00019.png new file mode 100644 index 000000000..3a161194e Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_changeThreshold/00019.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00000.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00000.png new file mode 100644 index 000000000..d4a6a1beb Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00000.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00001.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00001.png new file mode 100644 index 000000000..84fdc3028 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00001.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00002.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00002.png new file mode 100644 index 000000000..a67fa2cf4 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00002.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00003.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00003.png new file mode 100644 index 000000000..a41088be5 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00003.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00004.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00004.png new file mode 100644 index 000000000..84a03b31c Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00004.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00005.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00005.png new file mode 100644 index 000000000..a364ad97f Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00005.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00006.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00006.png new file mode 100644 index 000000000..c1d53a3b0 Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00006.png differ diff --git a/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00007.png b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00007.png new file mode 100644 index 000000000..3a161194e Binary files /dev/null and b/tests/ragger/snapshots/nanosp/test_gcs_nested_execTransaction_send/00007.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00001.png index bd2d7cd4a..f8bcb28e7 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00002.png index 51d3a4333..51dd34355 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00003.png index 8d43105a0..88adf2301 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00004.png index 9a742dcd4..029666eb5 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00005.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00005.png index e91ac495d..d099b3971 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00005.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00006.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00006.png index 6af743494..151567457 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00006.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00006.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00010.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00010.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00010.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering-verbose/00010.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00001.png index bd2d7cd4a..f8bcb28e7 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00002.png index 51d3a4333..51dd34355 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00003.png index 8d43105a0..88adf2301 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00004.png index 9a742dcd4..029666eb5 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00005.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00005.png index e91ac495d..d099b3971 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00005.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00006.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00006.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00006.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering/00006.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00001.png index a81dcf9df..8f3d6fa22 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00002.png index 5dafa039d..fef4ad5c5 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00003.png index 6f1a4c9dc..8a51a7d94 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_permit/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00001.png index 80dc3d3f8..6ccc0b593 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00002.png index 35b028313..f17e55f80 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00003.png index 8ab66ec55..688d18df1 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_filtering_unlimited/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00001.png index 8e09324b4..0fa4f627d 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00002.png index fc037fb8c..1beb09d7e 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00003.png index 9585bfa84..b96ff34f0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-False-True/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00001.png index 8e09324b4..0fa4f627d 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00002.png index 38877a18b..d834673e2 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00003.png index 5cf1a1685..970d3f2d2 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_missing_token-True-False/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00002.png index 9b6572c39..780bd0e0e 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png index 9b6572c39..780bd0e0e 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00002.png index 6c0876a4a..38a6be5cb 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png index 9b6572c39..780bd0e0e 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00002.png index 6c0876a4a..38a6be5cb 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png index 51ec19b7f..f6da292ec 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00002.png index 51ec19b7f..f6da292ec 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png index 920a683b0..eb89471c0 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png index 51ec19b7f..f6da292ec 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png index 6d7f20ea6..30677da69 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png and b/tests/ragger/snapshots/nanox/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata/00000.png b/tests/ragger/snapshots/nanox/test_eip712_calldata/00000.png new file mode 100644 index 000000000..53f11c4a5 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata/00001.png b/tests/ragger/snapshots/nanox/test_eip712_calldata/00001.png new file mode 100644 index 000000000..99c1b1fff Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata/00002.png b/tests/ragger/snapshots/nanox/test_eip712_calldata/00002.png new file mode 100644 index 000000000..2c053aacc Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata/00003.png b/tests/ragger/snapshots/nanox/test_eip712_calldata/00003.png new file mode 100644 index 000000000..33d1209ad Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata/00004.png b/tests/ragger/snapshots/nanox/test_eip712_calldata/00004.png new file mode 100644 index 000000000..55bb5c874 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata/00005.png b/tests/ragger/snapshots/nanox/test_eip712_calldata/00005.png new file mode 100644 index 000000000..ab20baec2 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00000.png b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00000.png new file mode 100644 index 000000000..53f11c4a5 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00001.png b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00001.png new file mode 100644 index 000000000..99c1b1fff Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00002.png b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00002.png new file mode 100644 index 000000000..a67fa2cf4 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00003.png b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00003.png new file mode 100644 index 000000000..a41088be5 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00004.png b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00004.png new file mode 100644 index 000000000..84a03b31c Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00005.png b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00005.png new file mode 100644 index 000000000..55bb5c874 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00006.png b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00006.png new file mode 100644 index 000000000..ab20baec2 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_eip712_calldata_empty_send/00006.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00001.png b/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00001.png index 7da2e2bc7..4df874c29 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00001.png and b/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00002.png b/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00002.png index a785d5e60..eea95ad22 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00002.png and b/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00003.png b/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00003.png index d2d03be54..55bb5c874 100644 Binary files a/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00003.png and b/tests/ragger/snapshots/nanox/test_eip712_filtering_empty_array/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00000.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00000.png new file mode 100644 index 000000000..bbbe24644 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00001.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00001.png new file mode 100644 index 000000000..84fdc3028 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00002.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00002.png new file mode 100644 index 000000000..ee2d2f4f8 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00003.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00003.png new file mode 100644 index 000000000..c28978ef9 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00004.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00004.png new file mode 100644 index 000000000..4270f4121 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00005.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00005.png new file mode 100644 index 000000000..e81be2796 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00006.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00006.png new file mode 100644 index 000000000..f4c030b64 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00006.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00007.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00007.png new file mode 100644 index 000000000..9b0acaf72 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00007.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00008.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00008.png new file mode 100644 index 000000000..5ed42309b Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00008.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00009.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00009.png new file mode 100644 index 000000000..23ec6c2e0 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00009.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00010.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00010.png new file mode 100644 index 000000000..d3382db05 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00010.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00011.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00011.png new file mode 100644 index 000000000..e076302d8 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00011.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00012.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00012.png new file mode 100644 index 000000000..d4a0e7118 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00012.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00013.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00013.png new file mode 100644 index 000000000..103f494a7 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00013.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00014.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00014.png new file mode 100644 index 000000000..96900c61e Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00014.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00015.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00015.png new file mode 100644 index 000000000..055fd25c6 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00015.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00016.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00016.png new file mode 100644 index 000000000..c1d53a3b0 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00016.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00017.png b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00017.png new file mode 100644 index 000000000..3a161194e Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_createProxyWithNonce/00017.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png new file mode 100644 index 000000000..d4a6a1beb Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png new file mode 100644 index 000000000..84fdc3028 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png new file mode 100644 index 000000000..5da961930 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png new file mode 100644 index 000000000..bb5c900b8 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png new file mode 100644 index 000000000..37002344e Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png new file mode 100644 index 000000000..9e163788f Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png new file mode 100644 index 000000000..f4c030b64 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png new file mode 100644 index 000000000..ce9f0b665 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png new file mode 100644 index 000000000..f29f9bb4d Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png new file mode 100644 index 000000000..a3246e6a5 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00009.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00010.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00010.png new file mode 100644 index 000000000..de922bf7c Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00010.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00011.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00011.png new file mode 100644 index 000000000..e57699cb6 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00011.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00012.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00012.png new file mode 100644 index 000000000..ec5d9aa51 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00012.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00013.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00013.png new file mode 100644 index 000000000..74048f7e0 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00013.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00014.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00014.png new file mode 100644 index 000000000..8fb196ef4 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00014.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00015.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00015.png new file mode 100644 index 000000000..00bff5704 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00015.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00016.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00016.png new file mode 100644 index 000000000..be0cc92fc Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00016.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00017.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00017.png new file mode 100644 index 000000000..832f12e0e Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00017.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00018.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00018.png new file mode 100644 index 000000000..9abde7556 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00018.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00019.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00019.png new file mode 100644 index 000000000..c1d53a3b0 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00019.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00020.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00020.png new file mode 100644 index 000000000..3a161194e Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_addOwnerWithThreshold/00020.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00000.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00000.png new file mode 100644 index 000000000..d4a6a1beb Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00001.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00001.png new file mode 100644 index 000000000..84fdc3028 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00002.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00002.png new file mode 100644 index 000000000..5da961930 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00003.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00003.png new file mode 100644 index 000000000..bb5c900b8 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00004.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00004.png new file mode 100644 index 000000000..903f828d7 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00005.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00005.png new file mode 100644 index 000000000..c2b42b346 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00006.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00006.png new file mode 100644 index 000000000..ce9f0b665 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00006.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00007.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00007.png new file mode 100644 index 000000000..f29f9bb4d Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00007.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00008.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00008.png new file mode 100644 index 000000000..a3246e6a5 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00008.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00009.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00009.png new file mode 100644 index 000000000..de922bf7c Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00009.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00010.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00010.png new file mode 100644 index 000000000..e57699cb6 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00010.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00011.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00011.png new file mode 100644 index 000000000..ec5d9aa51 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00011.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00012.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00012.png new file mode 100644 index 000000000..38954e410 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00012.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00013.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00013.png new file mode 100644 index 000000000..2dc3e5c04 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00013.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00014.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00014.png new file mode 100644 index 000000000..887efbf97 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00014.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00015.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00015.png new file mode 100644 index 000000000..54eed8c27 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00015.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00016.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00016.png new file mode 100644 index 000000000..dbf850787 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00016.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00017.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00017.png new file mode 100644 index 000000000..27be46c04 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00017.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00018.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00018.png new file mode 100644 index 000000000..c1d53a3b0 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00018.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00019.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00019.png new file mode 100644 index 000000000..3a161194e Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_changeThreshold/00019.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00000.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00000.png new file mode 100644 index 000000000..d4a6a1beb Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00000.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00001.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00001.png new file mode 100644 index 000000000..84fdc3028 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00001.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00002.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00002.png new file mode 100644 index 000000000..a67fa2cf4 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00002.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00003.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00003.png new file mode 100644 index 000000000..a41088be5 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00003.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00004.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00004.png new file mode 100644 index 000000000..84a03b31c Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00004.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00005.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00005.png new file mode 100644 index 000000000..a364ad97f Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00005.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00006.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00006.png new file mode 100644 index 000000000..c1d53a3b0 Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00006.png differ diff --git a/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00007.png b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00007.png new file mode 100644 index 000000000..3a161194e Binary files /dev/null and b/tests/ragger/snapshots/nanox/test_gcs_nested_execTransaction_send/00007.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00000.png index eb8072d46..1539025d9 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00001.png index 37698d348..d9e8438a0 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00002.png index 91fa3b130..e82a36e85 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00003.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00003.png index 290074492..c06088798 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00003.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00004.png index fbea72d8f..798b268cd 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00004.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/multiple1/00006.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00006.png similarity index 100% rename from tests/ragger/snapshots/stax/test_settings/multiple1/00006.png rename to tests/ragger/snapshots/stax/test_eip712_advanced_filtering-verbose/00006.png diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00000.png index eb8072d46..3d2bc00d4 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00001.png index 37698d348..e1d7f7c96 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00002.png index 91fa3b130..81efae949 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00003.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00003.png index fbea72d8f..a46f44cfd 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00003.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_settings/debug_token/00005.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00005.png similarity index 100% rename from tests/ragger/snapshots/stax/test_settings/debug_token/00005.png rename to tests/ragger/snapshots/stax/test_eip712_advanced_filtering/00005.png diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00001.png index c57d9b8b5..b30556830 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00006.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00004.png similarity index 100% rename from tests/ragger/snapshots/stax/test_tx_simulation_sign_threat/00006.png rename to tests/ragger/snapshots/stax/test_eip712_advanced_filtering_permit/00004.png diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00001.png index 9d2c54edf..406e2dd59 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_filtering_unlimited/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00001.png index 85b8c5362..b1e942a9a 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-False-True/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00001.png index ae760ec38..d7dc0447a 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_missing_token-True-False/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00001.png index 356c1897f..a66c4011f 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png index 356c1897f..a66c4011f 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00001.png index 225f6427e..3caca2d9d 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png index 356c1897f..a66c4011f 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_account_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00001.png index 225f6427e..3caca2d9d 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png index 9beedee22..f6450ffe1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_account_contract/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00001.png index 9beedee22..f6450ffe1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png index 9beedee22..f6450ffe1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_advanced_trusted_name_contract_with_contract_account/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata/00000.png b/tests/ragger/snapshots/stax/test_eip712_calldata/00000.png new file mode 100644 index 000000000..e6d003ca2 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata/00001.png b/tests/ragger/snapshots/stax/test_eip712_calldata/00001.png new file mode 100644 index 000000000..0c618be17 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata/00002.png b/tests/ragger/snapshots/stax/test_eip712_calldata/00002.png new file mode 100644 index 000000000..49db249a1 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata/00003.png b/tests/ragger/snapshots/stax/test_eip712_calldata/00003.png new file mode 100644 index 000000000..cfee3aec2 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata/00004.png b/tests/ragger/snapshots/stax/test_eip712_calldata/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00000.png b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00000.png new file mode 100644 index 000000000..e6d003ca2 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00001.png b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00001.png new file mode 100644 index 000000000..f1f004df7 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00002.png b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00002.png new file mode 100644 index 000000000..49db249a1 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00003.png b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00003.png new file mode 100644 index 000000000..cfee3aec2 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00004.png b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_calldata_empty_send/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00000.png b/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00000.png index eb8072d46..e6d003ca2 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00000.png and b/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00001.png b/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00001.png index efce2dfe6..8225ce8dd 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00001.png and b/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00002.png b/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00002.png index fbea72d8f..49db249a1 100644 Binary files a/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00002.png and b/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00004.png b/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_eip712_filtering_empty_array/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00000.png b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00000.png new file mode 100644 index 000000000..9d762168e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00001.png b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00001.png new file mode 100644 index 000000000..6980f0f5e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00002.png b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00002.png new file mode 100644 index 000000000..0ea28e8f6 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00003.png b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00003.png new file mode 100644 index 000000000..9ca17080d Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00004.png b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00004.png new file mode 100644 index 000000000..087b8429e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00005.png b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00005.png new file mode 100644 index 000000000..fb57e21c0 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00006.png b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00006.png new file mode 100644 index 000000000..392165d4f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00007.png b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00007.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_createProxyWithNonce/00007.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png new file mode 100644 index 000000000..4066e912e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png new file mode 100644 index 000000000..8c91f6223 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png new file mode 100644 index 000000000..dda423e9a Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png new file mode 100644 index 000000000..999eb3e14 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png new file mode 100644 index 000000000..4ad3d4832 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png new file mode 100644 index 000000000..056124f55 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png new file mode 100644 index 000000000..5bdbbee1f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png new file mode 100644 index 000000000..392165d4f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00007.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_addOwnerWithThreshold/00008.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00000.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00000.png new file mode 100644 index 000000000..4066e912e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00001.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00001.png new file mode 100644 index 000000000..4d1945a33 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00002.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00002.png new file mode 100644 index 000000000..a0ef81346 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00003.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00003.png new file mode 100644 index 000000000..35ef36123 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00004.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00004.png new file mode 100644 index 000000000..7e20f30c9 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00005.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00005.png new file mode 100644 index 000000000..cd6c56638 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00005.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00006.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00006.png new file mode 100644 index 000000000..5bdbbee1f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00006.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00007.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00007.png new file mode 100644 index 000000000..392165d4f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00007.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00008.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00008.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_changeThreshold/00008.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00000.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00000.png new file mode 100644 index 000000000..6ebd3ff3e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00001.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00001.png new file mode 100644 index 000000000..0b42f33e1 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00002.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00002.png new file mode 100644 index 000000000..b44617836 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00003.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00003.png new file mode 100644 index 000000000..392165d4f Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00004.png b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00004.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_gcs_nested_execTransaction_send/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_safe_descriptor/00000.png b/tests/ragger/snapshots/stax/test_safe_descriptor/00000.png new file mode 100644 index 000000000..404519549 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_safe_descriptor/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_safe_descriptor/00001.png b/tests/ragger/snapshots/stax/test_safe_descriptor/00001.png new file mode 100644 index 000000000..ba228db5e Binary files /dev/null and b/tests/ragger/snapshots/stax/test_safe_descriptor/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_safe_descriptor/00002.png b/tests/ragger/snapshots/stax/test_safe_descriptor/00002.png new file mode 100644 index 000000000..4cba550b3 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_safe_descriptor/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_safe_descriptor/00003.png b/tests/ragger/snapshots/stax/test_safe_descriptor/00003.png new file mode 100644 index 000000000..339db1b45 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_safe_descriptor/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00000.png index f6af04db0..733006bb6 100644 Binary files a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00000.png and b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00000.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00001.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00001.png index cff110344..8225ce8dd 100644 Binary files a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00001.png and b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00001.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00002.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00002.png index efce2dfe6..088fa83c9 100644 Binary files a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00002.png and b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00002.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00003.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00003.png index 6de7d8741..cfee3aec2 100644 Binary files a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00003.png and b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00003.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00004.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00004.png index cfee3aec2..339db1b45 100644 Binary files a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00004.png and b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/00004.png differ diff --git a/tests/ragger/snapshots/stax/test_tx_simulation_eip712/warning/00000.png b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/warning/00000.png new file mode 100644 index 000000000..f6af04db0 Binary files /dev/null and b/tests/ragger/snapshots/stax/test_tx_simulation_eip712/warning/00000.png differ diff --git a/tests/ragger/test_eip712.py b/tests/ragger/test_eip712.py index 64b346987..a25556228 100644 --- a/tests/ragger/test_eip712.py +++ b/tests/ragger/test_eip712.py @@ -1,37 +1,54 @@ import fnmatch import os -from functools import partial from pathlib import Path import json -from typing import Optional +from typing import Optional, Callable from ctypes import c_uint64 +import hashlib + import pytest from eth_account.messages import encode_typed_data import web3 -from ledgered.devices import Device - from ragger.backend import BackendInterface -from ragger.firmware.touch.positions import POSITIONS -from ragger.navigator import Navigator, NavInsID, NavIns +from ragger.navigator import NavigateWithScenario from ragger.error import ExceptionRAPDU import client.response_parser as ResponseParser -from client.utils import recover_message -from client.client import EthAppClient, TrustedNameType, TrustedNameSource +from client.utils import recover_message, get_selector_from_data +from client.client import EthAppClient, TrustedNameType, TrustedNameSource, EIP712CalldataParamPresence from client.status_word import StatusWord from client.eip712 import InputData from client.settings import SettingID, settings_toggle from client.tx_simu import TxSimu from client.proxy_info import ProxyInfo +from client.gcs import ( + Field, ParamType, ParamRaw, Value, TypeFamily, DataPath, PathTuple, ParamTrustedName, + ParamNFT, ParamDatetime, DatetimeType, ParamTokenAmount, ParamToken, ParamCalldata, + ParamAmount, ContainerPath, PathLeaf, PathLeafType, PathRef, PathArray, TxInfo +) + BIP32_PATH = "m/44'/60'/0'/0/0" -autonext_idx: int -snapshots_dirname: Optional[str] = None -WALLET_ADDR: Optional[bytes] = None -validate_warning: bool = False -skip_flow: bool = False +DEVICE_ADDR: Optional[bytes] = None + + +def set_wallet_addr(backend: BackendInterface) -> bytes: + global DEVICE_ADDR + + # don't ask again if we already have it + if DEVICE_ADDR is None: + client = EthAppClient(backend) + with client.get_public_addr(display=False): + pass + _, DEVICE_ADDR, _ = ResponseParser.pk_addr(client.response().data) + + +@pytest.fixture(autouse=True) +def init_wallet_addr(backend: BackendInterface): + """Initialize wallet address before each test""" + set_wallet_addr(backend) def eip712_json_path() -> str: @@ -61,34 +78,16 @@ def filtering_fixture(request) -> bool: return request.param -def get_wallet_addr(client: EthAppClient) -> bytes: - global WALLET_ADDR - - # don't ask again if we already have it - if WALLET_ADDR is None: - with client.get_public_addr(display=False): - pass - _, WALLET_ADDR, _ = ResponseParser.pk_addr(client.response().data) - return WALLET_ADDR - - -def test_eip712_v0(backend: BackendInterface, - navigator: Navigator, - simu_params: Optional[TxSimu] = None): - global validate_warning - - app_client = EthAppClient(backend) - device = backend.device +def test_eip712_v0(scenario_navigator: NavigateWithScenario, simu_params: Optional[TxSimu] = None): + app_client = EthAppClient(scenario_navigator.backend) - DEVICE_ADDR = get_wallet_addr(app_client) - - settings_toggle(device, navigator, [SettingID.BLIND_SIGNING]) + settings_toggle(scenario_navigator.backend.device, scenario_navigator.navigator, [SettingID.BLIND_SIGNING]) with open(input_files()[0], encoding="utf-8") as file: data = json.load(file) smsg = encode_typed_data(full_message=data) if simu_params is not None: - validate_warning = True + set_wallet_addr(scenario_navigator.backend) simu_params.from_addr = DEVICE_ADDR simu_params.tx_hash = smsg.body simu_params.domain_hash = smsg.header @@ -96,99 +95,31 @@ def test_eip712_v0(backend: BackendInterface, assert response.status == StatusWord.OK with app_client.eip712_sign_legacy(BIP32_PATH, smsg.header, smsg.body): - moves = [] - if device.is_nano: - moves += [NavInsID.BOTH_CLICK] - moves += [NavInsID.RIGHT_CLICK] * 5 - moves += [NavInsID.BOTH_CLICK] - else: - moves += [NavInsID.USE_CASE_CHOICE_REJECT] - moves += [NavInsID.SWIPE_CENTER_TO_LEFT] * 2 - moves += [NavInsID.USE_CASE_REVIEW_CONFIRM] - navigator.navigate(moves) + scenario_navigator.review_approve_with_warning(do_comparison=False) vrs = ResponseParser.signature(app_client.response().data) assert DEVICE_ADDR == recover_message(data, vrs) -def autonext(device: Device, navigator: Navigator, default_screenshot_path: Path): - global autonext_idx +def eip712_new_common(scenario_navigator: NavigateWithScenario, + data: dict, + filters: Optional[dict] = None, + snapshots_dirname: Optional[str] = None, + with_warning: bool = False) -> bytes: + app_client = EthAppClient(scenario_navigator.backend) - moves = [] - if device.is_nano: - if autonext_idx == 0 and validate_warning: - moves = [NavInsID.BOTH_CLICK] - else: - moves = [NavInsID.RIGHT_CLICK] - else: - if autonext_idx == 0 and validate_warning: - moves = [NavInsID.USE_CASE_CHOICE_REJECT] - else: - if autonext_idx == 2 and skip_flow: - InputData.disable_autonext() # so the timer stops firing - moves = [ - # Ragger does not handle the skip button - NavIns(NavInsID.TOUCH, POSITIONS["RightHeader"][device.type]), - NavInsID.USE_CASE_CHOICE_CONFIRM, - ] - else: - moves = [NavInsID.SWIPE_CENTER_TO_LEFT] - if snapshots_dirname is not None: - navigator.navigate_and_compare(default_screenshot_path, - snapshots_dirname, - moves, - screen_change_before_first_instruction=False, - screen_change_after_last_instruction=False, - snap_start_idx=autonext_idx) - else: - navigator.navigate(moves, - screen_change_before_first_instruction=False, - screen_change_after_last_instruction=False) - autonext_idx += len(moves) - - -def eip712_new_common(device: Device, - navigator: Navigator, - default_screenshot_path: Path, - app_client: EthAppClient, - json_data: dict, - filters: Optional[dict], - golden_run: bool): - global autonext_idx - global validate_warning - global skip_flow - global snapshots_dirname - - autonext_idx = 0 - assert InputData.process_data(app_client, - json_data, - filters, - partial(autonext, device, navigator, default_screenshot_path), - golden_run) + InputData.process_data(app_client, data, filters) + do_compare = snapshots_dirname is not None with app_client.eip712_sign_new(BIP32_PATH): - if device.is_nano: - nav_ins = NavInsID.RIGHT_CLICK - val_ins = NavInsID.BOTH_CLICK - text = "Sign message" + if with_warning: + # Warning screen + scenario_navigator.review_approve_with_warning(test_name=snapshots_dirname, do_comparison=do_compare) else: - nav_ins = NavInsID.SWIPE_CENTER_TO_LEFT - val_ins = NavInsID.USE_CASE_REVIEW_CONFIRM - text = "Hold to sign" - if snapshots_dirname is not None: - navigator.navigate_until_text_and_compare(nav_ins, - [val_ins], - text, - default_screenshot_path, - snapshots_dirname, - snap_start_idx=autonext_idx) - else: - navigator.navigate_until_text(nav_ins, [val_ins], text) - # reset values - validate_warning = False - skip_flow = False - snapshots_dirname = None + scenario_navigator.review_approve(test_name=snapshots_dirname, do_comparison=do_compare) - return ResponseParser.signature(app_client.response().data) + vrs = ResponseParser.signature(app_client.response().data) + # verify signature + assert DEVICE_ADDR == recover_message(data, vrs) def get_filter_file_from_data_file(data_file: Path) -> Path: @@ -196,17 +127,11 @@ def get_filter_file_from_data_file(data_file: Path) -> Path: return Path(f"{test_path}-filter.json") -def test_eip712_new(backend: BackendInterface, - navigator: Navigator, - default_screenshot_path: Path, +def test_eip712_new(scenario_navigator: NavigateWithScenario, input_file: Path, verbose_raw: bool, filtering: bool): - global validate_warning - settings_to_toggle: list[SettingID] = [] - app_client = EthAppClient(backend) - device = backend.device filters = None if filtering: @@ -222,25 +147,12 @@ def test_eip712_new(backend: BackendInterface, if verbose_raw: settings_to_toggle.append(SettingID.VERBOSE_EIP712) - if not filters or verbose_raw: - validate_warning = True - if len(settings_to_toggle) > 0: - settings_toggle(device, navigator, settings_to_toggle) + settings_toggle(scenario_navigator.backend.device, scenario_navigator.navigator, settings_to_toggle) with open(input_file, encoding="utf-8") as file: data = json.load(file) - vrs = eip712_new_common(device, - navigator, - default_screenshot_path, - app_client, - data, - filters, - False) - - recovered_addr = recover_message(data, vrs) - - assert recovered_addr == get_wallet_addr(app_client) + eip712_new_common(scenario_navigator, data, filters, with_warning=bool(not filters or verbose_raw)) class DataSet(): @@ -461,52 +373,25 @@ def data_set_fixture(request) -> DataSet: return request.param -def test_eip712_advanced_filtering(backend: BackendInterface, - navigator: Navigator, - default_screenshot_path: Path, +def test_eip712_advanced_filtering(scenario_navigator: NavigateWithScenario, test_name: str, data_set: DataSet, - golden_run: bool, verbose_raw: bool): - global snapshots_dirname - if verbose_raw and data_set.suffix: pytest.skip("Skipping Verbose mode for this data sets") - app_client = EthAppClient(backend) - device = backend.device - snapshots_dirname = test_name + data_set.suffix if verbose_raw: - settings_toggle(device, navigator, [SettingID.DISPLAY_HASH]) + settings_toggle(scenario_navigator.backend.device, scenario_navigator.navigator, [SettingID.DISPLAY_HASH]) snapshots_dirname += "-verbose" - vrs = eip712_new_common(device, - navigator, - default_screenshot_path, - app_client, - data_set.data, - data_set.filters, - golden_run) - - # verify signature - addr = recover_message(data_set.data, vrs) - assert addr == get_wallet_addr(app_client) + eip712_new_common(scenario_navigator, data_set.data, data_set.filters, snapshots_dirname) -def test_eip712_filtering_empty_array(backend: BackendInterface, - navigator: Navigator, - default_screenshot_path: Path, +def test_eip712_filtering_empty_array(scenario_navigator: NavigateWithScenario, test_name: str, - golden_run: bool, simu_params: Optional[TxSimu] = None): - global snapshots_dirname - global validate_warning - - app_client = EthAppClient(backend) - device = backend.device - - snapshots_dirname = test_name + app_client = EthAppClient(scenario_navigator.backend) data = { "types": { @@ -573,24 +458,14 @@ def test_eip712_filtering_empty_array(backend: BackendInterface, } if simu_params is not None: - validate_warning = True + set_wallet_addr(scenario_navigator.backend) smsg = encode_typed_data(full_message=data) simu_params.tx_hash = smsg.body simu_params.domain_hash = smsg.header response = app_client.provide_tx_simulation(simu_params) assert response.status == StatusWord.OK - vrs = eip712_new_common(device, - navigator, - default_screenshot_path, - app_client, - data, - filters, - golden_run) - - # verify signature - addr = recover_message(data, vrs) - assert addr == get_wallet_addr(app_client) + eip712_new_common(scenario_navigator, data, filters, test_name, with_warning=bool(simu_params is not None)) TOKENS = [ @@ -620,19 +495,10 @@ def tokens_fixture(request) -> list[dict]: return request.param -def test_eip712_advanced_missing_token(backend: BackendInterface, - navigator: Navigator, - default_screenshot_path: Path, +def test_eip712_advanced_missing_token(scenario_navigator: NavigateWithScenario, test_name: str, - tokens: list[dict], - golden_run: bool): - global snapshots_dirname - + tokens: list[dict]): test_name += f"-{len(tokens[0]) == 0}-{len(tokens[1]) == 0}" - snapshots_dirname = test_name - - app_client = EthAppClient(backend) - device = backend.device data = { "types": { @@ -688,17 +554,8 @@ def test_eip712_advanced_missing_token(backend: BackendInterface, }, } } - vrs = eip712_new_common(device, - navigator, - default_screenshot_path, - app_client, - data, - filters, - golden_run) - # verify signature - addr = recover_message(data, vrs) - assert addr == get_wallet_addr(app_client) + eip712_new_common(scenario_navigator, data, filters, test_name) TRUSTED_NAMES = [ @@ -724,22 +581,15 @@ def filt_tn_types_fixture(request) -> list[TrustedNameType]: return request.param -def test_eip712_advanced_trusted_name(backend: BackendInterface, - navigator: Navigator, - default_screenshot_path: Path, +def test_eip712_advanced_trusted_name(scenario_navigator: NavigateWithScenario, test_name: str, trusted_name: tuple, - filt_tn_types: list[TrustedNameType], - golden_run: bool): - global snapshots_dirname - + filt_tn_types: list[TrustedNameType]): test_name += f"_{trusted_name[0].name.lower()}_with" for t in filt_tn_types: test_name += f"_{t.name.lower()}" - snapshots_dirname = test_name - app_client = EthAppClient(backend) - device = backend.device + app_client = EthAppClient(scenario_navigator.backend) data = { "types": { @@ -794,73 +644,17 @@ def test_eip712_advanced_trusted_name(backend: BackendInterface, trusted_name[1], data["domain"]["chainId"], challenge=challenge) - vrs = eip712_new_common(device, - navigator, - default_screenshot_path, - app_client, - data, - filters, - golden_run) - - # verify signature - addr = recover_message(data, vrs) - assert addr == get_wallet_addr(app_client) + eip712_new_common(scenario_navigator, data, filters, test_name) -def test_eip712_bs_not_activated_error(backend: BackendInterface, - navigator: Navigator, - default_screenshot_path: Path): - app_client = EthAppClient(backend) - device = backend.device - +def test_eip712_bs_not_activated_error(scenario_navigator: NavigateWithScenario): with pytest.raises(ExceptionRAPDU) as e: - eip712_new_common(device, - navigator, - default_screenshot_path, - app_client, - ADVANCED_DATA_SETS[0].data, - None, - False) - InputData.disable_autonext() # so the timer stops firing + eip712_new_common(scenario_navigator, ADVANCED_DATA_SETS[0].data) assert e.value.status == StatusWord.INVALID_DATA -def test_eip712_skip(backend: BackendInterface, - navigator: Navigator, - default_screenshot_path: Path, - golden_run: bool): - global validate_warning - global skip_flow - - app_client = EthAppClient(backend) - device = backend.device - - if device.is_nano: - pytest.skip("Not supported on Nano devices") - - validate_warning = True - skip_flow = True - settings_toggle(device, navigator, [SettingID.BLIND_SIGNING]) - with open(input_files()[0], encoding="utf-8") as file: - data = json.load(file) - vrs = eip712_new_common(device, - navigator, - default_screenshot_path, - app_client, - data, - None, - golden_run) - - # verify signature - addr = recover_message(data, vrs) - assert addr == get_wallet_addr(app_client) - - -def test_eip712_proxy(backend: BackendInterface, - navigator: Navigator, - default_screenshot_path: Path): - app_client = EthAppClient(backend) - device = backend.device +def test_eip712_proxy(scenario_navigator: NavigateWithScenario): + app_client = EthAppClient(scenario_navigator.backend) input_file = input_files()[0] with open(input_file, encoding="utf-8") as file: @@ -880,14 +674,100 @@ def test_eip712_proxy(backend: BackendInterface, app_client.provide_proxy_info(proxy_info.serialize()) - vrs = eip712_new_common(device, - navigator, - default_screenshot_path, - app_client, - data, - filters, - False) + eip712_new_common(scenario_navigator, data, filters) + + +def gcs_handler(app_client: EthAppClient, json_data: dict) -> None: + fields = [ + Field( + 1, + "Amount", + ParamTokenAmount( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(1), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + token=Value( + 1, + TypeFamily.ADDRESS, + container_path=ContainerPath.TO, + ), + ) + ), + ] + # compute instructions hash + inst_hash = hashlib.sha3_256() + for field in fields: + inst_hash.update(field.serialize()) + tx_info = TxInfo( + 1, + json_data["domain"]["chainId"], + bytes.fromhex(json_data["message"]["to"][2:]), + get_selector_from_data(json_data["message"]["data"]), + inst_hash.digest(), + "Token transfer", + contract_name="USDC", + ) + app_client.provide_token_metadata(tx_info.contract_name, tx_info.contract_addr, 6, tx_info.chain_id) - # verify signature - addr = recover_message(data, vrs) - assert addr == get_wallet_addr(app_client) + app_client.provide_transaction_info(tx_info.serialize()) + + for field in fields: + app_client.provide_transaction_field_desc(field.serialize()) + + +def eip712_calldata_common(scenario_navigator: NavigateWithScenario, + test_name: str, + filename: str, + handler: Optional[Callable] = None): + with open("%s/%s.json" % (eip712_json_path(), filename)) as file: + data = json.load(file) + + filters = { + "name": "Calldata test", + "calldatas": [ + { + "index": 0, + "handler": handler, + "value_flag": True, + "callee_flag": EIP712CalldataParamPresence.PRESENT_FILTERED, + "chain_id_flag": False, + "selector_flag": False, + "amount_flag": True, + "spender_flag": EIP712CalldataParamPresence.NONE, + }, + ], + "fields": { + "to": { + "type": "calldata_callee", + "index": 0, + }, + "value": { + "type": "calldata_amount", + "index": 0, + }, + "data": { + "type": "calldata_value", + "index": 0, + }, + } + } + + eip712_new_common(scenario_navigator, data, filters, test_name) + + +def test_eip712_calldata(scenario_navigator: NavigateWithScenario, test_name: str): + eip712_calldata_common(scenario_navigator, test_name, "safe", gcs_handler) + + +def test_eip712_calldata_empty_send(scenario_navigator: NavigateWithScenario, test_name: str): + eip712_calldata_common(scenario_navigator, test_name, "safe_empty") diff --git a/tests/ragger/test_gcs.py b/tests/ragger/test_gcs.py index fa1d7dd8b..547629bfa 100644 --- a/tests/ragger/test_gcs.py +++ b/tests/ragger/test_gcs.py @@ -1,5 +1,4 @@ from typing import Optional -import struct import json import hashlib from web3 import Web3 @@ -15,8 +14,8 @@ from client.utils import get_selector_from_data from client.gcs import ( Field, ParamType, ParamRaw, Value, TypeFamily, DataPath, PathTuple, ParamTrustedName, - ParamNFT, ParamDatetime, DatetimeType, ParamTokenAmount, ParamToken, ContainerPath, - PathLeaf, PathLeafType, PathRef, PathArray, TxInfo + ParamNFT, ParamDatetime, DatetimeType, ParamTokenAmount, ParamToken, ParamCalldata, + ParamAmount, ContainerPath, PathLeaf, PathLeafType, PathRef, PathArray, TxInfo ) from client.tx_simu import TxSimu from client.proxy_info import ProxyInfo @@ -68,7 +67,6 @@ def test_gcs_nft(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "From", - ParamType.TRUSTED_NAME, ParamTrustedName( 1, Value( @@ -100,7 +98,6 @@ def test_gcs_nft(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "To", - ParamType.RAW, ParamRaw( 1, Value( @@ -119,7 +116,6 @@ def test_gcs_nft(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "NFTs", - ParamType.NFT, ParamNFT( 1, Value( @@ -146,7 +142,6 @@ def test_gcs_nft(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "Values", - ParamType.RAW, ParamRaw( 1, Value( @@ -168,7 +163,6 @@ def test_gcs_nft(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "Data", - ParamType.RAW, ParamRaw( 1, Value( @@ -212,10 +206,9 @@ def test_gcs_nft(scenario_navigator: NavigateWithScenario, test_name: str): app_client.provide_nft_metadata("OpenSea Shared Storefront", tx_params["to"], tx_params["chainId"]) for field in fields: - payload = field.serialize() - app_client.send_raw(0xe0, 0x28, 0x01, 0x00, struct.pack(">H", len(payload)) + payload) + app_client.provide_transaction_field_desc(field.serialize()) - with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): + with app_client.sign(mode=SignMode.START_FLOW): scenario_navigator.review_approve(test_name=test_name) @@ -264,7 +257,6 @@ def test_gcs_poap(scenario_navigator: NavigateWithScenario, Field( 1, "Event ID", - ParamType.RAW, ParamRaw( 1, Value( @@ -284,7 +276,6 @@ def test_gcs_poap(scenario_navigator: NavigateWithScenario, Field( 1, "Token ID", - ParamType.RAW, ParamRaw( 1, Value( @@ -304,7 +295,6 @@ def test_gcs_poap(scenario_navigator: NavigateWithScenario, Field( 1, "Receiver", - ParamType.RAW, ParamRaw( 1, Value( @@ -323,7 +313,6 @@ def test_gcs_poap(scenario_navigator: NavigateWithScenario, Field( 1, "Expiration time", - ParamType.DATETIME, ParamDatetime( 1, Value( @@ -344,7 +333,6 @@ def test_gcs_poap(scenario_navigator: NavigateWithScenario, Field( 1, "Signature", - ParamType.RAW, ParamRaw( 1, Value( @@ -385,10 +373,9 @@ def test_gcs_poap(scenario_navigator: NavigateWithScenario, app_client.provide_transaction_info(tx_info.serialize()) for field in fields: - payload = field.serialize() - app_client.send_raw(0xe0, 0x28, 0x01, 0x00, struct.pack(">H", len(payload)) + payload) + app_client.provide_transaction_field_desc(field.serialize()) - with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): + with app_client.sign(mode=SignMode.START_FLOW): if simu_params is not None: scenario_navigator.review_approve_with_warning(test_name=test_name) else: @@ -434,7 +421,6 @@ def test_gcs_1inch(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "Executor", - ParamType.RAW, ParamRaw( 1, Value( @@ -453,7 +439,6 @@ def test_gcs_1inch(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "Send", - ParamType.TOKEN_AMOUNT, ParamTokenAmount( 1, Value( @@ -489,7 +474,6 @@ def test_gcs_1inch(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "Receive", - ParamType.TOKEN_AMOUNT, ParamTokenAmount( 1, Value( @@ -548,10 +532,9 @@ def test_gcs_1inch(scenario_navigator: NavigateWithScenario, test_name: str): app_client.provide_token_metadata("USDC", bytes.fromhex("A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), 6, 1) for field in fields: - payload = field.serialize() - app_client.send_raw(0xe0, 0x28, 0x01, 0x00, struct.pack(">H", len(payload)) + payload) + app_client.provide_transaction_field_desc(field.serialize()) - with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): + with app_client.sign(mode=SignMode.START_FLOW): scenario_navigator.review_approve(test_name=test_name) @@ -586,7 +569,6 @@ def test_gcs_proxy(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "New owner", - ParamType.TRUSTED_NAME, ParamTrustedName( 1, Value( @@ -657,10 +639,9 @@ def test_gcs_proxy(scenario_navigator: NavigateWithScenario, test_name: str): challenge=ResponseParser.challenge(app_client.get_challenge().data)) for field in fields: - payload = field.serialize() - app_client.send_raw(0xe0, 0x28, 0x01, 0x00, struct.pack(">H", len(payload)) + payload) + app_client.provide_transaction_field_desc(field.serialize()) - with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): + with app_client.sign(mode=SignMode.START_FLOW): scenario_navigator.review_approve(test_name=test_name) @@ -694,7 +675,6 @@ def test_gcs_4226(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "Deposit asset", - ParamType.TOKEN_AMOUNT, ParamTokenAmount( 1, Value( @@ -719,7 +699,6 @@ def test_gcs_4226(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "Receive shares", - ParamType.TOKEN, ParamToken( 1, Value( @@ -732,8 +711,7 @@ def test_gcs_4226(scenario_navigator: NavigateWithScenario, test_name: str): Field( 1, "Send shares to", - ParamType.RAW, - ParamToken( + ParamRaw( 1, Value( 1, @@ -775,8 +753,1115 @@ def test_gcs_4226(scenario_navigator: NavigateWithScenario, test_name: str): app_client.provide_token_metadata("SWELL", swell_token_addr, 18, 1) for field in fields: - payload = field.serialize() - app_client.send_raw(0xe0, 0x28, 0x01, 0x00, struct.pack(">H", len(payload)) + payload) + app_client.provide_transaction_field_desc(field.serialize()) + + with app_client.sign(mode=SignMode.START_FLOW): + scenario_navigator.review_approve(test_name=test_name) + + +# https://etherscan.io/tx/0x07a80f1b359146129f3369af39e7eb2457581109c8300fc2ef81e997a07cf3f0 +def test_gcs_nested_createProxyWithNonce(scenario_navigator: NavigateWithScenario, test_name: str): + backend = scenario_navigator.backend + app_client = EthAppClient(backend) + + with open(f"{ABIS_FOLDER}/safe_l2_setup_1.4.1.abi.json", encoding="utf-8") as f: + safe_l2_setup = Web3().eth.contract( + abi=json.load(f), + address=bytes.fromhex("BD89A1CE4DDe368FFAB0eC35506eEcE0b1fFdc54") + ) + safe_l2_setup_data = safe_l2_setup.encode_abi("setupToL2", [ + bytes.fromhex("29fcB43b46531BcA003ddC8FCB67FFE91900C762") + ]) + with open(f"{ABIS_FOLDER}/safe_1.4.1.abi.json", encoding="utf-8") as f: + safe = Web3().eth.contract( + abi=json.load(f), + address=bytes.fromhex("41675C099F32341bf84BFc5382aF534df5C7461a") + ) + safe_data = safe.encode_abi("setup", [ + [ + bytes.fromhex("6535d5F76F021FE65E2ac73D086dF4b4Bd7ee5D9"), + bytes.fromhex("3fB2C8699C3D0Cedde210F383435C537C86D91B8") + ], + 2, + safe_l2_setup.address, + safe_l2_setup_data, + bytes.fromhex("fd0732Dc9E303f09fCEf3a7388Ad10A83459Ec99"), + bytes.fromhex("0000000000000000000000000000000000000000"), + 0, + bytes.fromhex("5afe7A11E7000000000000000000000000000000") + ]) + with open(f"{ABIS_FOLDER}/safe_proxy_factory_1.4.1.abi.json", encoding="utf-8") as f: + safe_proxy_factory = Web3().eth.contract( + abi=json.load(f), + address=bytes.fromhex("4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67") + ) + data = safe_proxy_factory.encode_abi("createProxyWithNonce", [ + safe.address, + safe_data, + 0 + ]) + tx_params = { + "nonce": 75, + "maxFeePerGas": Web3.to_wei(4.2, "gwei"), + "maxPriorityFeePerGas": Web3.to_wei(2, "gwei"), + "gas": 291314, + "to": safe_proxy_factory.address, + "data": data, + "chainId": 1 + } + + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): + pass + + fields = [ + Field( + 1, + "_singleton", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "initializer", + ParamCalldata( + 1, + Value( + 1, + TypeFamily.BYTES, + data_path=DataPath( + 1, + [ + PathTuple(1), + PathRef(), + PathLeaf(PathLeafType.DYNAMIC), + ] + ), + ), + Value( + 1, + TypeFamily.BYTES, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "saltNonce", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(2), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + ] + + # compute instructions hash + inst_hash = hashlib.sha3_256() + for field in fields: + inst_hash.update(field.serialize()) + + tx_info = TxInfo( + 1, + tx_params["chainId"], + tx_params["to"], + get_selector_from_data(tx_params["data"]), + inst_hash.digest(), + "create a Safe account", + creator_name="Safe", + creator_legal_name="Safe Ecosystem Foundation", + creator_url="safe.global", + ) + + app_client.provide_transaction_info(tx_info.serialize()) + + sub_fields = [ + Field( + 1, + "_owners", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathRef(), + PathArray(1), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "_threshold", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(1), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "to", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(2), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "data", + ParamCalldata( + 1, + Value( + 1, + TypeFamily.BYTES, + data_path=DataPath( + 1, + [ + PathTuple(3), + PathRef(), + PathLeaf(PathLeafType.DYNAMIC), + ] + ), + ), + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(2), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "fallbackHandler", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(4), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "paymentToken", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(5), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "payment", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(6), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "paymentReceiver", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(7), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + ] + # compute instructions hash + sub_inst_hash = hashlib.sha3_256() + for sub_field in sub_fields: + sub_inst_hash.update(sub_field.serialize()) + + sub_tx_info = TxInfo( + 1, + tx_params["chainId"], + safe.address, + get_selector_from_data(safe_data), + sub_inst_hash.digest(), + "setup", + ) + + sub_sub_fields = [ + Field( + 1, + "l2Singleton", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + ] + # compute instructions hash + sub_sub_inst_hash = hashlib.sha3_256() + for sub_sub_field in sub_sub_fields: + sub_sub_inst_hash.update(sub_sub_field.serialize()) + sub_sub_tx_info = TxInfo( + 1, + tx_params["chainId"], + safe_l2_setup.address, + get_selector_from_data(safe_l2_setup_data), + sub_sub_inst_hash.digest(), + "L2 setup", + ) + + for field in fields: + app_client.provide_transaction_field_desc(field.serialize()) + if field.param.type == ParamType.CALLDATA: + app_client.provide_transaction_info(sub_tx_info.serialize()) + for sub_field in sub_fields: + app_client.provide_transaction_field_desc(sub_field.serialize()) + if sub_field.param.type == ParamType.CALLDATA: + app_client.provide_transaction_info(sub_sub_tx_info.serialize()) + for sub_sub_field in sub_sub_fields: + app_client.provide_transaction_field_desc(sub_sub_field.serialize()) + + with app_client.sign(mode=SignMode.START_FLOW): + scenario_navigator.review_approve(test_name=test_name) + + +# https://etherscan.io/tx/0xc5545f13bfaf6f69ae937bc64337405060dc56ce7649ea7051d2bbc3b4316b79 +def test_gcs_nested_execTransaction_send(scenario_navigator: NavigateWithScenario, test_name: str): + backend = scenario_navigator.backend + app_client = EthAppClient(backend) + + with open(f"{ABIS_FOLDER}/safe_1.4.1.abi.json", encoding="utf-8") as f: + contract = Web3().eth.contract( + abi=json.load(f), + address=bytes.fromhex("23F8abfC2824C397cCB3DA89ae772984107dDB99") + ) + data = contract.encode_abi("execTransaction", [ + contract.address, + Web3.to_wei(0.0042, "ether"), + bytes(), + 0, + 0, + 0, + 0, + bytes.fromhex("0000000000000000000000000000000000000000"), + bytes.fromhex("0000000000000000000000000000000000000000"), + bytes.fromhex("a974345670d8e06c52eeb7bfe59b1ed0fc879223ff0938c859c3852110c8c58016ec4bf0c68e84d3a40e3ac519f0a0db6954e7c4107fc6985de7dc683603f62a1b"), + ]) + + tx_params = { + "nonce": 77, + "maxFeePerGas": Web3.to_wei(4.8, "gwei"), + "maxPriorityFeePerGas": Web3.to_wei(2, "gwei"), + "gas": 95118, + "to": bytes.fromhex("C1897a9Acbdd54028dA5f7b76B5833A91553AaF6"), + "data": data, + "chainId": 1 + } + + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): + pass + + fields = [ + Field( + 1, + "data", + ParamCalldata( + 1, + Value( + 1, + TypeFamily.BYTES, + data_path=DataPath( + 1, + [ + PathTuple(2), + PathRef(), + PathLeaf(PathLeafType.DYNAMIC), + ] + ), + ), + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + amount=Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(1), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + spender=Value( + 1, + TypeFamily.ADDRESS, + container_path=ContainerPath.TO, + ), + ) + ), + ] + + # compute instructions hash + inst_hash = hashlib.sha3_256() + for field in fields: + inst_hash.update(field.serialize()) + + tx_info = TxInfo( + 1, + tx_params["chainId"], + tx_params["to"], + get_selector_from_data(tx_params["data"]), + inst_hash.digest(), + "execute a Safe action", + creator_name="Safe", + creator_legal_name="Safe Ecosystem Foundation", + creator_url="safe.global", + ) + + app_client.provide_transaction_info(tx_info.serialize()) + + for field in fields: + app_client.provide_transaction_field_desc(field.serialize()) + + with app_client.sign(mode=SignMode.START_FLOW): + scenario_navigator.review_approve(test_name=test_name) + + +# https://etherscan.io/tx/0xbeafe22c9e3ddcf85b06f65a56cc3ea8f5b02c323cc433c93c103ad3526db88d +def test_gcs_nested_execTransaction_addOwnerWithThreshold(scenario_navigator: NavigateWithScenario, test_name: str): + backend = scenario_navigator.backend + app_client = EthAppClient(backend) + + with open(f"{ABIS_FOLDER}/safe_1.4.1.abi.json", encoding="utf-8") as f: + contract = Web3().eth.contract( + abi=json.load(f), + address=bytes.fromhex("23F8abfC2824C397cCB3DA89ae772984107dDB99") + ) + sub_data = contract.encode_abi("addOwnerWithThreshold", [ + bytes.fromhex("FD6765Ad4eE64668701356a16aB28B123B3A4170"), + 2 + ]) + data = contract.encode_abi("execTransaction", [ + contract.address, + Web3.to_wei(0, "ether"), + sub_data, + 0, + 0, + 0, + 0, + bytes.fromhex("0000000000000000000000000000000000000000"), + bytes.fromhex("0000000000000000000000000000000000000000"), + bytes.fromhex("c14660c23f715fc85c01326c7fa7f05ddeb71147fc7bad912eace6ee55c24a314f814262b3c8ca64fc77377ce6e65b20bdc902c34931888c433e23ab0069843d1bf3d2dfb18fd6bd807002bffec3326755c928e325981f30e1518e999b348a5f011446931b8bd9fbb152cdc00d945b7cd030c14e48c7826d31f9c09a1376f694de1b"), + ]) + + tx_params = { + "nonce": 78, + "maxFeePerGas": Web3.to_wei(8.9, "gwei"), + "maxPriorityFeePerGas": Web3.to_wei(2, "gwei"), + "gas": 168740, + "to": contract.address, + "data": data, + "chainId": 1 + } + + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): + pass + + fields = [ + Field( + 1, + "to", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "value", + ParamAmount( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(1), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "data", + ParamCalldata( + 1, + Value( + 1, + TypeFamily.BYTES, + data_path=DataPath( + 1, + [ + PathTuple(2), + PathRef(), + PathLeaf(PathLeafType.DYNAMIC), + ] + ), + ), + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "operation", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=1, + data_path=DataPath( + 1, + [ + PathTuple(3), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "safeTxGas", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(4), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "dataGas", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(5), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "gasPrice", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(6), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "gasToken", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(7), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "refundReceiver", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(8), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "signatures", + ParamRaw( + 1, + Value( + 1, + TypeFamily.BYTES, + data_path=DataPath( + 1, + [ + PathTuple(9), + PathRef(), + PathLeaf(PathLeafType.DYNAMIC), + ] + ), + ), + ) + ), + ] + + # compute instructions hash + inst_hash = hashlib.sha3_256() + for field in fields: + inst_hash.update(field.serialize()) + + tx_info = TxInfo( + 1, + tx_params["chainId"], + tx_params["to"], + get_selector_from_data(tx_params["data"]), + inst_hash.digest(), + "execute a Safe action", + creator_name="Safe", + creator_legal_name="Safe Ecosystem Foundation", + creator_url="safe.global", + ) + + app_client.provide_transaction_info(tx_info.serialize()) + + sub_fields = [ + Field( + 1, + "owner", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "_threshold", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(1), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + ] + # compute instructions hash + sub_inst_hash = hashlib.sha3_256() + for sub_field in sub_fields: + sub_inst_hash.update(sub_field.serialize()) + + sub_tx_info = TxInfo( + 1, + tx_params["chainId"], + contract.address, + get_selector_from_data(sub_data), + sub_inst_hash.digest(), + "add owner with threshold", + ) + + for field in fields: + app_client.provide_transaction_field_desc(field.serialize()) + if field.param.type == ParamType.CALLDATA: + app_client.provide_transaction_info(sub_tx_info.serialize()) + for sub_field in sub_fields: + app_client.provide_transaction_field_desc(sub_field.serialize()) + + with app_client.sign(mode=SignMode.START_FLOW): + scenario_navigator.review_approve(test_name=test_name) + + +# https://etherscan.io/tx/0x5047fedc98f46d2afd94d0a2813ddf0c8fe777ec0739ffd327586a91e1e5a89a +def test_gcs_nested_execTransaction_changeThreshold(scenario_navigator: NavigateWithScenario, test_name: str): + backend = scenario_navigator.backend + app_client = EthAppClient(backend) + + with open(f"{ABIS_FOLDER}/safe_1.4.1.abi.json", encoding="utf-8") as f: + contract = Web3().eth.contract( + abi=json.load(f), + address=bytes.fromhex("23F8abfC2824C397cCB3DA89ae772984107dDB99") + ) + sub_data = contract.encode_abi("changeThreshold", [ + 3 + ]) + data = contract.encode_abi("execTransaction", [ + contract.address, + Web3.to_wei(0, "ether"), + sub_data, + 0, + 0, + 0, + 0, + bytes.fromhex("0000000000000000000000000000000000000000"), + bytes.fromhex("0000000000000000000000000000000000000000"), + bytes.fromhex("d3a6ddfb9dffe883d609129d9e87dda928a4a9b9d5d2f4a93879d03ccb0d32b12df7dcf9acd9c5f73443c82b0e01183794436a381148cf2fb928f7df776a01701b2fc9ebbc15bfdae0f5ef1b6f4ad1389d31f1dc137e51e7a184e255fd0ed065911ad684bd97ee43892013b4eebdaec528020ed657b92b90562f4df5a18540e4b91b"), + ]) + + tx_params = { + "nonce": 83, + "maxFeePerGas": Web3.to_wei(5.7, "gwei"), + "maxPriorityFeePerGas": Web3.to_wei(2, "gwei"), + "gas": 98318, + "to": contract.address, + "data": data, + "chainId": 1 + } + + with app_client.sign("m/44'/60'/0'/0/0", tx_params, mode=SignMode.STORE): + pass + + fields = [ + Field( + 1, + "to", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "value", + ParamAmount( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(1), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "data", + ParamCalldata( + 1, + Value( + 1, + TypeFamily.BYTES, + data_path=DataPath( + 1, + [ + PathTuple(2), + PathRef(), + PathLeaf(PathLeafType.DYNAMIC), + ] + ), + ), + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "operation", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=1, + data_path=DataPath( + 1, + [ + PathTuple(3), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "safeTxGas", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(4), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "dataGas", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(5), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "gasPrice", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(6), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "gasToken", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(7), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "refundReceiver", + ParamRaw( + 1, + Value( + 1, + TypeFamily.ADDRESS, + data_path=DataPath( + 1, + [ + PathTuple(8), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + Field( + 1, + "signatures", + ParamRaw( + 1, + Value( + 1, + TypeFamily.BYTES, + data_path=DataPath( + 1, + [ + PathTuple(9), + PathRef(), + PathLeaf(PathLeafType.DYNAMIC), + ] + ), + ), + ) + ), + ] + + # compute instructions hash + inst_hash = hashlib.sha3_256() + for field in fields: + inst_hash.update(field.serialize()) + + tx_info = TxInfo( + 1, + tx_params["chainId"], + tx_params["to"], + get_selector_from_data(tx_params["data"]), + inst_hash.digest(), + "execute a Safe action", + creator_name="Safe", + creator_legal_name="Safe Ecosystem Foundation", + creator_url="safe.global", + ) + + app_client.provide_transaction_info(tx_info.serialize()) + + sub_fields = [ + Field( + 1, + "newThreshold", + ParamRaw( + 1, + Value( + 1, + TypeFamily.UINT, + type_size=32, + data_path=DataPath( + 1, + [ + PathTuple(0), + PathLeaf(PathLeafType.STATIC), + ] + ), + ), + ) + ), + ] + # compute instructions hash + sub_inst_hash = hashlib.sha3_256() + for sub_field in sub_fields: + sub_inst_hash.update(sub_field.serialize()) + + sub_tx_info = TxInfo( + 1, + tx_params["chainId"], + contract.address, + get_selector_from_data(sub_data), + sub_inst_hash.digest(), + "change threshold", + ) + + for field in fields: + app_client.provide_transaction_field_desc(field.serialize()) + if field.param.type == ParamType.CALLDATA: + app_client.provide_transaction_info(sub_tx_info.serialize()) + for sub_field in sub_fields: + app_client.provide_transaction_field_desc(sub_field.serialize()) - with app_client.send_raw_async(0xe0, 0x04, 0x00, 0x02, bytes()): + with app_client.sign(mode=SignMode.START_FLOW): scenario_navigator.review_approve(test_name=test_name) diff --git a/tests/ragger/test_safe.py b/tests/ragger/test_safe.py new file mode 100644 index 000000000..173608404 --- /dev/null +++ b/tests/ragger/test_safe.py @@ -0,0 +1,98 @@ +import pytest + +from ragger.navigator.navigation_scenario import NavigateWithScenario +from ragger.error import ExceptionRAPDU + +from client.client import EthAppClient +from client.status_word import StatusWord +from client.safe import SafeAccount, AccountType, LesMultiSigRole +import client.response_parser as ResponseParser + + + +def common(app_client: EthAppClient) -> int: + challenge = app_client.get_challenge() + return ResponseParser.challenge(challenge.data) + + +def test_safe_descriptor(scenario_navigator: NavigateWithScenario, + test_name: str) -> None: + """Test the Safe descriptor APDU""" + + backend = scenario_navigator.backend + app_client = EthAppClient(backend) + device = backend.device + + if device.is_nano: + pytest.skip("Not yet supported on Nano") + + challenge = common(app_client) + + signer = SafeAccount( + AccountType.SIGNER, + challenge, + [ + bytes.fromhex("1"*40), + bytes.fromhex("2"*40), + bytes.fromhex("3"*40), + bytes.fromhex("4"*40), + bytes.fromhex("5"*40), + bytes.fromhex("6"*40), + bytes.fromhex("7"*40), + bytes.fromhex("8"*40), + bytes.fromhex("9"*40), + bytes.fromhex("a"*40), + bytes.fromhex("b"*40), + bytes.fromhex("c"*40), + bytes.fromhex("d"*40), + bytes.fromhex("e"*40), + bytes.fromhex("f"*40), + ], + ) + safe = SafeAccount( + AccountType.SAFE, + challenge, + [bytes.fromhex("5a321744667052affa8386ed49e00ef223cbffc3")], + LesMultiSigRole.PROPOSER, + 5, + len(signer.address), + ) + + with app_client.provide_safe_account(safe): + # Safe descriptor doesn't start any navigation + pass + response = app_client.response() + assert response.status == StatusWord.OK, f"Unexpected status: {response.status}" + + with app_client.provide_safe_account(signer): + scenario_navigator.address_review_approve(test_name=test_name) + response = app_client.response() + assert response.status == StatusWord.OK, f"Unexpected status: {response.status}" + + +def test_signer_descriptor_error(scenario_navigator: NavigateWithScenario) -> None: + """Test the SaSignerfe descriptor APDU""" + + backend = scenario_navigator.backend + app_client = EthAppClient(backend) + device = backend.device + + if device.is_nano: + pytest.skip("Not yet supported on Nano") + + challenge = common(app_client) + + signer = SafeAccount( + account_type=AccountType.SIGNER, + challenge=challenge, + address=[bytes.fromhex("1"*40)], + ) + + try: + with app_client.provide_safe_account(signer): + # Safe descriptor doesn't start any navigation + pass + except ExceptionRAPDU as e: + assert e.status == StatusWord.CONDITION_NOT_SATISFIED + else: + assert False, "Expected CONDITION_NOT_SATISFIED not raised" diff --git a/tests/ragger/test_trusted_name.py b/tests/ragger/test_trusted_name.py index c581984af..e009227a5 100644 --- a/tests/ragger/test_trusted_name.py +++ b/tests/ragger/test_trusted_name.py @@ -76,7 +76,8 @@ def test_trusted_name_v1_verbose(navigator: Navigator, moves += [NavInsID.SWIPE_CENTER_TO_LEFT] ENS_POSITIONS = { DeviceType.FLEX: (420, 380), - DeviceType.STAX: (350, 360) + DeviceType.STAX: (350, 360), + DeviceType.APEX_P: (270, 250) } moves += [NavIns(NavInsID.TOUCH, ENS_POSITIONS[device.type])] moves += [NavInsID.LEFT_HEADER_TAP] diff --git a/tests/ragger/test_tx_simulation.py b/tests/ragger/test_tx_simulation.py index 3627488e0..bfb4dd0ef 100644 --- a/tests/ragger/test_tx_simulation.py +++ b/tests/ragger/test_tx_simulation.py @@ -294,44 +294,36 @@ def test_tx_simulation_eip191(navigator: Navigator, simu_params) -def test_tx_simulation_eip712(backend: BackendInterface, - navigator: Navigator, - test_name: str, - default_screenshot_path: Path) -> None: +def test_tx_simulation_eip712(scenario_navigator: NavigateWithScenario, test_name: str) -> None: """Test the TX Simulation APDU with a Message Streaming based on EIP712""" - app_client = EthAppClient(backend) - device = backend.device + app_client = EthAppClient(scenario_navigator.backend) - if device.is_nano: + if scenario_navigator.backend.device.is_nano: pytest.skip("Not yet supported on Nano") - __common_setting_handling(device, navigator, app_client, True) + __common_setting_handling(scenario_navigator.backend.device, scenario_navigator.navigator, app_client, True) simu_params = __get_simu_params("threat", SimuType.TYPED_DATA) - sign_eip712(backend, - navigator, - default_screenshot_path, + sign_eip712(scenario_navigator, test_name, - False, simu_params) -def test_tx_simulation_eip712_v0(backend: BackendInterface, navigator: Navigator) -> None: +def test_tx_simulation_eip712_v0(scenario_navigator: NavigateWithScenario) -> None: """Test the TX Simulation APDU with a Message Streaming based on EIP712_v0""" - app_client = EthAppClient(backend) - device = backend.device + app_client = EthAppClient(scenario_navigator.backend) - if device.is_nano: + if scenario_navigator.backend.device.is_nano: pytest.skip("Not yet supported on Nano") - __common_setting_handling(device, navigator, app_client, True) + __common_setting_handling(scenario_navigator.backend.device, scenario_navigator.navigator, app_client, True) simu_params = __get_simu_params("threat", SimuType.TYPED_DATA) - sign_eip712_v0(backend, navigator, simu_params) + sign_eip712_v0(scenario_navigator, simu_params) def test_tx_simulation_gcs(navigator: Navigator, diff --git a/tools/copy_clones.sh b/tools/copy_clones.sh index 1a065d13e..fb4437450 100755 --- a/tools/copy_clones.sh +++ b/tools/copy_clones.sh @@ -1,6 +1,6 @@ #!/bin/bash -DEVICES=(nanos2 nanox stax flex) +DEVICES=(nanos2 nanox stax flex apex_p apex_m) for dev in "${DEVICES[@]}"; do elf_file="build/${dev}/bin/app.elf" diff --git a/tools/gen_dynamic_network.py b/tools/gen_dynamic_network.py index 1cd9303db..8b7bc0e71 100755 --- a/tools/gen_dynamic_network.py +++ b/tools/gen_dynamic_network.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import os +import struct import subprocess import sys import logging @@ -64,9 +65,9 @@ class P2Type(IntEnum): def init_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="Generate hex string for network icon, in NBGL format.") parser.add_argument("--icon", "-i", help="Input icon to process.") - parser.add_argument("--name", "-n", required=True, help="Network name") - parser.add_argument("--ticker", "-t", required=True, help="Network ticker") - parser.add_argument("--chainid", "-c", type=int, required=True, help="Network chain_id") + parser.add_argument("--name", "-n", help="Network name") + parser.add_argument("--ticker", "-t", help="Network ticker") + parser.add_argument("--chainid", "-c", type=int, help="Network chain_id") parser.add_argument("--verbose", "-v", action='store_true', help="Verbose mode") return parser @@ -191,17 +192,22 @@ def generate_tlv_payload(name: str, bytes: The generated TLV payload. """ - payload: bytes = format_tlv(NetworkInfoTag.STRUCTURE_TYPE, 8) - payload += format_tlv(NetworkInfoTag.STRUCTURE_VERSION, 1) - payload += format_tlv(NetworkInfoTag.BLOCKCHAIN_FAMILY, 1) - payload += format_tlv(NetworkInfoTag.CHAIN_ID, chain_id.to_bytes(8, 'big')) - payload += format_tlv(NetworkInfoTag.NETWORK_NAME, name.encode('utf-8')) - payload += format_tlv(NetworkInfoTag.TICKER, ticker.encode('utf-8')) + tlv_payload: bytes = format_tlv(NetworkInfoTag.STRUCTURE_TYPE, 8) + tlv_payload += format_tlv(NetworkInfoTag.STRUCTURE_VERSION, 1) + tlv_payload += format_tlv(NetworkInfoTag.BLOCKCHAIN_FAMILY, 1) + tlv_payload += format_tlv(NetworkInfoTag.CHAIN_ID, chain_id.to_bytes(8, 'big')) + tlv_payload += format_tlv(NetworkInfoTag.NETWORK_NAME, name.encode('utf-8')) + tlv_payload += format_tlv(NetworkInfoTag.TICKER, ticker.encode('utf-8')) if icon: # Network Icon Hash - payload += format_tlv(NetworkInfoTag.NETWORK_ICON_HASH, sha256(icon).digest()) + tlv_payload += format_tlv(NetworkInfoTag.NETWORK_ICON_HASH, sha256(icon).digest()) # Append the data Signature - payload += format_tlv(NetworkInfoTag.DER_SIGNATURE, sign_data(Key.NETWORK, payload)) + tlv_payload += format_tlv(NetworkInfoTag.DER_SIGNATURE, sign_data(Key.NETWORK, tlv_payload)) + + # Append the payload length and the data + payload: bytes = bytes() + payload += struct.pack(">H", len(tlv_payload)) + payload += tlv_payload # Return the constructed TLV payload as bytes return payload @@ -231,7 +237,7 @@ def prepare_network_information(name: str, # Check if the payload is larger than 0xff assert len(payload) < 0xff, "Payload too large" # Serialize the payload - chunks.append(serialize(0x00, P2Type.NETWORK_CONFIG, payload)) + chunks.append(serialize(0x01, P2Type.NETWORK_CONFIG, payload)) if icon: # Serialize the icon @@ -274,10 +280,11 @@ def main() -> None: else: image_data = None - chunks = prepare_network_information(args.name, args.ticker, args.chainid, image_data) - # Print each chunk with its index - for i, chunk in enumerate(chunks): - logger.info(f"Chunk {i}[{len(chunk)}]: {chunk.hex()}") + if args.chainid and args.name and args.ticker: + chunks = prepare_network_information(args.name, args.ticker, args.chainid, image_data) + # Print each chunk with its index + for i, chunk in enumerate(chunks): + logger.info(f"Chunk {i}[{len(chunk)}]: {chunk.hex()}") if __name__ == "__main__": diff --git a/tools/gen_networks.py b/tools/gen_networks.py index ba9cf763e..5778d65d2 100755 --- a/tools/gen_networks.py +++ b/tools/gen_networks.py @@ -5,6 +5,7 @@ import re import argparse from pathlib import Path +from functools import partial class Network: @@ -18,8 +19,16 @@ def __init__(self, chain_id: int, name: str, ticker: str): self.ticker = ticker -def get_network_glyph_name(net: Network) -> str: - return "chain_%u_64px" % (net.chain_id) +def get_network_glyph_size(path: str): + return 64 if path.split("/")[1] in ["stax", "flex"] else 48 + + +def get_network_glyph_name(net: Network, path: str) -> str: + return "chain_%u_%upx" % (net.chain_id, get_network_glyph_size(path)) + + +def get_network_glyph_path(net: Network, path: str) -> str: + return "glyphs/%s.gif" % (get_network_glyph_name(net, path)) def get_header() -> str: @@ -62,8 +71,8 @@ def gen_icons_array_src(networks: list[Network], path: str) -> bool: """ % (os.path.basename(path), len(networks)), file=out) for net in networks: - glyph_name = get_network_glyph_name(net) - glyph_file = "glyphs/%s.gif" % (glyph_name) + glyph_name = get_network_glyph_name(net, path) + glyph_file = get_network_glyph_path(net, path) if os.path.isfile(glyph_file): if os.path.islink(glyph_file): glyph_name = Path(os.path.realpath(glyph_file)).stem @@ -85,8 +94,8 @@ def gen_icons_array(networks: list[Network], path: str) -> bool: return True -def network_icon_exists(net: Network) -> bool: - return os.path.isfile("glyphs/%s.gif" % (get_network_glyph_name(net))) +def network_icon_exists(net: Network, path: str) -> bool: + return os.path.isfile(get_network_glyph_path(net, path)) def main(output_dir: str) -> bool: @@ -107,7 +116,8 @@ def main(output_dir: str) -> bool: networks.sort(key=lambda x: x.chain_id) - if not gen_icons_array(list(filter(network_icon_exists, networks)), + if not gen_icons_array(list(filter(partial(network_icon_exists, path=output_dir), + networks)), output_dir): return False return True diff --git a/tools/gen_tx_simulation.py b/tools/gen_tx_simulation.py index ae3f1e466..07ccba760 100755 --- a/tools/gen_tx_simulation.py +++ b/tools/gen_tx_simulation.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import sys +import struct import logging from enum import IntEnum from pathlib import Path @@ -116,20 +117,25 @@ def generate_tlv_payload(risk: int, # Construct the TLV payload tx_hash = bytes.fromhex("00"*32) if unknown else bytes.fromhex("deadbeaf"*8) - payload: bytes = format_tlv(TxSimulationTag.STRUCTURE_TYPE, 9) - payload += format_tlv(TxSimulationTag.STRUCTURE_VERSION, 1) - payload += format_tlv(TxSimulationTag.ADDRESS, bytes.fromhex(addr)) + tlv_payload: bytes = format_tlv(TxSimulationTag.STRUCTURE_TYPE, 9) + tlv_payload += format_tlv(TxSimulationTag.STRUCTURE_VERSION, 1) + tlv_payload += format_tlv(TxSimulationTag.ADDRESS, bytes.fromhex(addr)) if chain_id != 0: - payload += format_tlv(TxSimulationTag.CHAIN_ID, chain_id.to_bytes(8, 'big')) - payload += format_tlv(TxSimulationTag.TX_HASH, tx_hash) - payload += format_tlv(TxSimulationTag.TX_CHECKS_NORMALIZED_RISK, risk) - payload += format_tlv(TxSimulationTag.TX_CHECKS_NORMALIZED_CATEGORY, category) + tlv_payload += format_tlv(TxSimulationTag.CHAIN_ID, chain_id.to_bytes(8, 'big')) + tlv_payload += format_tlv(TxSimulationTag.TX_HASH, tx_hash) + tlv_payload += format_tlv(TxSimulationTag.TX_CHECKS_NORMALIZED_RISK, risk) + tlv_payload += format_tlv(TxSimulationTag.TX_CHECKS_NORMALIZED_CATEGORY, category) if message: - payload += format_tlv(TxSimulationTag.TX_CHECKS_PROVIDER_MSG, message.encode('utf-8')) - payload += format_tlv(TxSimulationTag.TX_CHECKS_TINY_URL, url.encode('utf-8')) - payload += format_tlv(TxSimulationTag.TX_CHECKS_SIMULATION_TYPE, 0) + tlv_payload += format_tlv(TxSimulationTag.TX_CHECKS_PROVIDER_MSG, message.encode('utf-8')) + tlv_payload += format_tlv(TxSimulationTag.TX_CHECKS_TINY_URL, url.encode('utf-8')) + tlv_payload += format_tlv(TxSimulationTag.TX_CHECKS_SIMULATION_TYPE, 0) # Append the data Signature - payload += format_tlv(TxSimulationTag.DER_SIGNATURE, sign_data(Key.TRANSACTION_CHECK, payload)) + tlv_payload += format_tlv(TxSimulationTag.DER_SIGNATURE, sign_data(Key.TRANSACTION_CHECK, tlv_payload)) + + # Append the payload length and the data + payload: bytes = bytes() + payload += struct.pack(">H", len(tlv_payload)) + payload += tlv_payload # Return the constructed TLV payload as bytes return payload diff --git a/tools/valground.py b/tools/valground.py index c40f96a73..79abc3d15 100755 --- a/tools/valground.py +++ b/tools/valground.py @@ -3,9 +3,31 @@ # pytest --device nanosp -s -k my_special_test 2>&1 | ./valground.py import sys +from argparse import ArgumentParser, Namespace, ArgumentDefaultsHelpFormatter, RawDescriptionHelpFormatter from typing import Optional +# =============================================================================== +# Summary class +# =============================================================================== +class GlobalSummary: + max_size: int + code_location: str + + def __init__(self): + self.max_size = 0 + + def update(self, size: int): + self.max_size = max(size, self.max_size) + + def summary(self): + print(f"\n{COLORS['fg_red']}{COLORS['bg_white']}=== Global ==={COLORS['all_reset']}") + print(f"{COLORS['fg_yellow']}Higher Max overtime = {self.max_size} bytes{COLORS['all_reset']}\n") + + +# =============================================================================== +# Allocation class +# =============================================================================== class Allocation: size: int code_location: str @@ -15,76 +37,221 @@ def __init__(self, size: int, code_location: str): self.code_location = code_location +# =============================================================================== +# Memory class +# =============================================================================== class Memory: allocs: dict[Allocation] + persists: dict[Allocation] allocd_overtime: int allocd_max: int allocd_current: int alloc_count: int addr: int size: int + test_name: str + free_errors: list[str] - def __init__(self, addr: int, size: int): + def __init__(self, addr: int, size: int, test_name: str) -> None: self.allocs = {} + self.persists = {} self.allocd_overtime = 0 self.allocd_max = 0 self.allocd_current = 0 self.alloc_count = 0 self.addr = addr self.size = size + self.test_name = test_name + self.free_errors = [] - def alloc(self, ptr: int, size: int, code_loc: str): - self.allocs[ptr] = Allocation(size, code_loc) + def alloc(self, ptr: int, size: int, code_loc: str, persist: bool) -> None: + if persist: + self.persists[ptr] = Allocation(size, code_loc) + else: + self.allocs[ptr] = Allocation(size, code_loc) self.allocd_current += size - if self.allocd_current > self.allocd_max: - self.allocd_max = self.allocd_current + self.allocd_max = max(self.allocd_max, self.allocd_current) self.allocd_overtime += size self.alloc_count += 1 - def free(self, ptr: int, code_loc: str): - assert ptr in self.allocs - self.allocd_current -= self.allocs[ptr].size - del self.allocs[ptr] + def free(self, ptr: int, code_loc: str) -> None: + if ptr not in self.allocs and ptr not in self.persists: + self.free_errors.append(code_loc) + return + if ptr in self.allocs: + self.allocd_current -= self.allocs[ptr].size + del self.allocs[ptr] + else: + self.allocd_current -= self.persists[ptr].size + del self.persists[ptr] + + def summary(self, quiet: bool = False) -> bool: + print("") + if self.test_name: + print(f"{COLORS['fg_blue']}{COLORS['bg_white']}{self.test_name}{COLORS['all_reset']}") + + if len(self.free_errors) == 0: + if not quiet: + print(f"{COLORS['fg_green']}No memory free errors detected, congrats!{COLORS['all_reset']}") + else: + print(f"{COLORS['fg_red']}Free without malloc, or double free detected:") + for code_loc in self.free_errors: + print(f"- {code_loc}") + print(f"{COLORS['all_reset']}", end='') - def __del__(self): if len(self.allocs) == 0: - print("No memory leak detected, congrats!") + if not quiet: + print(f"{COLORS['fg_green']}No memory leak detected, congrats!{COLORS['all_reset']}") else: - print("Memory leaks :") + print(f"{COLORS['fg_red']}Memory leaks:") for addr, info in self.allocs.items(): print("- [0x%.08x] %u bytes from %s" % (addr, info.size, info.code_location)) + print(f"{COLORS['all_reset']}", end='') + + global_summary.update(self.allocd_max) + if not quiet: + print("=== Summary ===") + print("Total overtime = %u bytes" % (self.allocd_overtime)) + used_percentage = self.allocd_max / self.size * 100 + info_str = f"Max overtime = {self.allocd_max} bytes ({used_percentage:.02f}% full)" + if used_percentage > 90: + print(f"{COLORS['fg_yellow']}{info_str}{COLORS['all_reset']}") + else: + print(info_str) + print("Allocations = %u" % (self.alloc_count)) + if len(self.persists) > 0: + print(f"{COLORS['fg_yellow']}Persistent memory allocations:") + for addr, info in list(self.persists.items()): + print(f"- {info.size} bytes from {info.code_location}") + del self.persists[addr] + print(f"{COLORS['all_reset']}", end='') + + return len(self.allocs) + len(self.free_errors) == 0 + - print("\n=== Summary ===") - print("Total overtime = %u bytes" % (self.allocd_overtime)) - used_percentage = self.allocd_max / self.size * 100 - print("Max overtime = %u bytes (%.02f%% full)" % (self.allocd_max, - used_percentage)) - print("Allocations = %u" % (self.alloc_count)) +# =============================================================================== +# Init colors +# =============================================================================== +def init_colors(enable_colors: bool) -> dict[str, str]: + """Initialize color variables based on colorama availability + ARGS: + enable_colors (bool): Flag to enable or disable colors + """ + colors = { + 'fg_green': '', + 'fg_red': '', + 'all_reset': '', + 'fg_yellow': '', + 'fg_blue': '', + 'bg_white': '' + } -mem: Optional[Memory] = None + if enable_colors: + try: + import colorama + colorama.init() # Initialize colorama + colors.update({ + 'fg_green': colorama.Fore.GREEN, + 'fg_red': colorama.Fore.RED, + 'all_reset': colorama.Fore.RESET + colorama.Back.RESET, + 'fg_yellow': colorama.Fore.YELLOW, + 'fg_blue': colorama.Fore.BLUE, + 'bg_white': colorama.Back.WHITE + }) + except ImportError: + print("To use colors, please install colorama: pip install colorama") -for line in sys.stdin: - line = line.rstrip() - scheme = "seproxyhal: printf: " - if line.startswith(scheme): - line = line[len(scheme):] - scheme = "==MP " + return colors + + +# =============================================================================== +# Parameters +# =============================================================================== +class CustomFormatter(ArgumentDefaultsHelpFormatter, RawDescriptionHelpFormatter): + """Custom formatter that combines ArgumentDefaultsHelpFormatter and RawDescriptionHelpFormatter""" + pass + +def init_parser() -> Namespace: + """Initialize the argument parser for command line arguments""" + epilog = "Compile the app with MEMORY_PROFILING=1 and feed the speculos output to this script.\n" + epilog += "Example usage: pytest --device nanosp -s -k my_special_test 2>&1 | ./valground.py" + parser = ArgumentParser(description="Analyze memory allocations to determine leaks.", + formatter_class=CustomFormatter, + epilog=epilog) + parser.add_argument("--quiet", "-q", action='store_true', help="Quiet logs to minimum.") + parser.add_argument("--colors", "-c", action='store_true', help="Enable colored output.") + return parser.parse_args() + + +# =============================================================================== +# Main entry +# =============================================================================== +def main() -> None: + mem: Optional[Memory] = None + + # Arguments parsing + # ----------------- + args = init_parser() + + # Initialize colors once at module level + global COLORS + COLORS = init_colors(args.colors) + + # Processing + # ---------- + ret_code = 0 + testnb = 0 + test_name = "" + for line in sys.stdin: + line = line.rstrip() + + # Only print lines that look like pytest test names + if line.startswith("collecting"): + line = line.replace("collecting ... ", "") + if line.startswith("collected"): + print(line) + nb_tests = int(line.split(" ")[-2]) + continue + if "test_" in line and "::" in line and "[" in line: + testnb += 1 + test_name = f"[{testnb}/{nb_tests}] - {line.split(' ')[0]}" + continue + + scheme = "seproxyhal: printf: " if line.startswith(scheme): line = line[len(scheme):] - words = line.split(";") - assert len(words) > 2 - - if words[0] == "init": - mem = Memory(int(words[1], base=0), int(words[2], base=0)) - elif words[0] == "alloc": - mem.alloc(int(words[2], base=0), int(words[1], base=0), words[3]) - elif words[0] == "free": - mem.free(int(words[1], base=0), words[2]) - else: - assert False + scheme = "==MP " + if line.startswith(scheme): + line = line[len(scheme):] + words = line.split(";") + assert len(words) > 2 + + if words[0] == "init": + # Print summary of previous test if exists + if mem is not None: + if mem.summary(args.quiet) is False: + ret_code = 1 + mem = Memory(int(words[1], base=0), int(words[2], base=0), test_name) + elif words[0] in ("alloc", "persist"): + mem.alloc(int(words[2], base=0), int(words[1], base=0), words[3], words[0] == "persist") + elif words[0] == "free": + mem.free(int(words[1], base=0), words[2]) + else: + assert False + + if mem is None: + print(f"{COLORS['fg_red']}No memory profiling was found.{COLORS['all_reset']}") + else: + if mem.summary(args.quiet) is False: + ret_code = 1 + global_summary.summary() + sys.exit(ret_code) + + +global_summary = GlobalSummary() -if mem is None: - print("No memory profiling was found.") +if __name__ == "__main__": + main()