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()